9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * CDDL HEADER START
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * The contents of this file are subject to the terms of the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Common Development and Distribution License (the "License").
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * You may not use this file except in compliance with the License.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * or http://www.opensolaris.org/os/licensing.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * See the License for the specific language governing permissions
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and limitations under the License.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * When distributing Covered Code, include this CDDL HEADER in each
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If applicable, add the following below this CDDL HEADER, with the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * fields enclosed by brackets "[]" replaced with your own identifying
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * information: Portions Copyright [yyyy] [name of copyright owner]
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * CDDL HEADER END
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon.c
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Hermon (InfiniBand) HCA Driver attach/detach Routines
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Implements all the routines necessary for the attach, setup,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * initialization (and subsequent possible teardown and detach) of the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Hermon InfiniBand HCA driver.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/types.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/file.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/open.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/conf.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/ddi.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/sunddi.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/modctl.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/stat.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/pci.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/pci_cap.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/bitmap.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/policy.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#include <sys/ib/adapters/hermon/hermon.h>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor/* /etc/system can tune this down, if that is desirable. */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylorint hermon_msix_max = HERMON_MSIX_MAX;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* The following works around a problem in pre-2_7_000 firmware. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#define HERMON_FW_WORKAROUND
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint hermon_verbose = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* Hermon HCA State Pointer */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorvoid *hermon_statep;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
332f545bce1434913a4e2bffd942656ef0906846Eiji Otaint debug_vpd = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
332f545bce1434913a4e2bffd942656ef0906846Eiji Ota/* Disable the internal error-check polling thread */
332f545bce1434913a4e2bffd942656ef0906846Eiji Otaint hermon_no_inter_err_chk = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * The Hermon "userland resource database" is common to instances of the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Hermon HCA driver. This structure "hermon_userland_rsrc_db" contains all
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the necessary information to maintain it.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_umap_db_t hermon_userland_rsrc_db;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_attach(dev_info_t *, ddi_attach_cmd_t);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_detach(dev_info_t *, ddi_detach_cmd_t);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_open(dev_t *, int, int, cred_t *);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_close(dev_t, int, int, cred_t *);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_drv_init(hermon_state_t *state, dev_info_t *dip,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int instance);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_drv_fini(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_drv_fini2(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_isr_init(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_isr_fini(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_hw_init(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_hw_fini(hermon_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_drv_cleanup_level_t cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_soft_state_init(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_soft_state_fini(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_icm_config_setup(hermon_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_initqueryhca_t *inithca);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_icm_tables_init(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_icm_tables_fini(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_icm_dma_init(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_icm_dma_fini(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_inithca_set(hermon_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_initqueryhca_t *inithca);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_hca_port_init(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_hca_ports_shutdown(hermon_state_t *state, uint_t num_init);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_internal_uarpg_init(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_internal_uarpg_fini(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_special_qp_contexts_reserve(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_special_qp_contexts_unreserve(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_sw_reset(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_mcg_init(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_mcg_fini(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_fw_version_check(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_device_info_report(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_pci_capability_list(hermon_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t hdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_pci_capability_vpd(hermon_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t hdl, uint_t offset);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_pci_read_vpd(ddi_acc_handle_t hdl, uint_t offset,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t addr, uint32_t *data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_intr_or_msi_init(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_add_intrs(hermon_state_t *state, int intr_type);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_intr_or_msi_fini(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorvoid hermon_pci_capability_msix(hermon_state_t *state, ddi_acc_handle_t hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t offset);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic uint64_t hermon_size_icm(hermon_state_t *state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* X86 fastreboot support */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic ushort_t get_msix_ctrl(dev_info_t *);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic size_t get_msix_tbl_size(dev_info_t *);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic size_t get_msix_pba_size(dev_info_t *);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void hermon_set_msix_info(hermon_state_t *);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_intr_disable(hermon_state_t *);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int hermon_quiesce(dev_info_t *);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* Character/Block Operations */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic struct cb_ops hermon_cb_ops = {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_open, /* open */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_close, /* close */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nodev, /* strategy (block) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nodev, /* print (block) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nodev, /* dump (block) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nodev, /* read */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nodev, /* write */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_ioctl, /* ioctl */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_devmap, /* devmap */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor NULL, /* mmap */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nodev, /* segmap */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nochpoll, /* chpoll */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_prop_op, /* prop_op */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor NULL, /* streams */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor D_NEW | D_MP |
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor D_64BIT | D_HOTPLUG |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor D_DEVMAP, /* flags */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor CB_REV /* rev */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor};
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* Driver Operations */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic struct dev_ops hermon_ops = {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor DEVO_REV, /* struct rev */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor 0, /* refcnt */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_getinfo, /* getinfo */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nulldev, /* identify */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nulldev, /* probe */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_attach, /* attach */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_detach, /* detach */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nodev, /* reset */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &hermon_cb_ops, /* cb_ops */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor NULL, /* bus_ops */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nodev, /* power */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_quiesce, /* devo_quiesce */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor};
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* Module Driver Info */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic struct modldrv hermon_modldrv = {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &mod_driverops,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "ConnectX IB Driver",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &hermon_ops
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor};
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* Module Linkage */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic struct modlinkage hermon_modlinkage = {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor MODREV_1,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &hermon_modldrv,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor NULL
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor};
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * This extern refers to the ibc_operations_t function vector that is defined
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * in the hermon_ci.c file.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorextern ibc_operations_t hermon_ibc_ops;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * _init()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor_init()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_soft_state_init(&hermon_statep, sizeof (hermon_state_t),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (size_t)HERMON_INITIAL_STATES);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ibc_init(&hermon_modlinkage);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_soft_state_fini(&hermon_statep);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = mod_install(&hermon_modlinkage);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibc_fini(&hermon_modlinkage);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_soft_state_fini(&hermon_statep);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize the Hermon "userland resources database" */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_umap_db_init();
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * _info()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor_info(struct modinfo *modinfop)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = mod_info(&hermon_modlinkage, modinfop);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * _fini()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor_fini()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = mod_remove(&hermon_modlinkage);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Destroy the Hermon "userland resources database" */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_umap_db_fini();
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibc_fini(&hermon_modlinkage);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_soft_state_fini(&hermon_statep);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_getinfo()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* ARGSUSED */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dev_t dev;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_state_t *state;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor minor_t instance;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (cmd) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case DDI_INFO_DEVT2DEVINFO:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dev = (dev_t)arg;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor instance = HERMON_DEV_INSTANCE(dev);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state = ddi_get_soft_state(hermon_statep, instance);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *result = (void *)state->hs_dip;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case DDI_INFO_DEVT2INSTANCE:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dev = (dev_t)arg;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor instance = HERMON_DEV_INSTANCE(dev);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *result = (void *)(uintptr_t)instance;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_open()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* ARGSUSED */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_open(dev_t *devp, int flag, int otyp, cred_t *credp)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_state_t *state;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_t *rsrcp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_umap_db_entry_t *umapdb, *umapdb2;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor minor_t instance;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t key, value;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t hr_indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dev_t dev;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor instance = HERMON_DEV_INSTANCE(*devp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state = ddi_get_soft_state(hermon_statep, instance);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ENXIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Only allow driver to be opened for character access, and verify
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * whether exclusive access is allowed.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((otyp != OTYP_CHR) || ((flag & FEXCL) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor secpolicy_excl_open(credp) != 0)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EINVAL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Search for the current process PID in the "userland resources
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * database". If it is not found, then attempt to allocate a UAR
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * page and add the ("key", "value") pair to the database.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: As a last step we always return a devp appropriate for
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the open. Either we return a new minor number (based on the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * instance and the UAR page index) or we return the current minor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * number for the given client process.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * We also add an entry to the database to allow for lookup from
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "dev_t" to the current process PID. This is necessary because,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * under certain circumstance, the process PID that calls the Hermon
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * close() entry point may not be the same as the one who called
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * open(). Specifically, this can happen if a child process calls
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the Hermon's open() entry point, gets a UAR page, maps it out (using
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * mmap()), and then exits without calling munmap(). Because mmap()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * adds a reference to the file descriptor, at the exit of the child
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * process the file descriptor is "inherited" by the parent (and will
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * be close()'d by the parent's PID only when it exits).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: We use the hermon_umap_db_find_nolock() and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_umap_db_add_nolock() database access routines below (with
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * an explicit mutex_enter of the database lock - "hdl_umapdb_lock")
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to ensure that the multiple accesses (in this case searching for,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and then adding _two_ database entries) can be done atomically.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor key = ddi_get_pid();
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&hermon_userland_rsrc_db.hdl_umapdb_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_umap_db_find_nolock(instance, key,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor MLNX_UMAP_UARPG_RSRC, &value, 0, NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If we are in 'maintenance mode', we cannot alloc a UAR page.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * But we still need some rsrcp value, and a mostly unique
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hr_indx value. So we set rsrcp to NULL for maintenance
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * mode, and use a rolling count for hr_indx. The field
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 'hs_open_hr_indx' is used only in this maintenance mode
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * condition.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Otherwise, if we are in operational mode then we allocate
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the UAR page as normal, and use the rsrcp value and tr_indx
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * value from that allocation.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (!HERMON_IS_OPERATIONAL(state->hs_operational_mode)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor rsrcp = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hr_indx = state->hs_open_ar_indx++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate a new UAR page for this process */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_rsrc_alloc(state, HERMON_UARPG, 1,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_NOSLEEP, &rsrcp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &hermon_userland_rsrc_db.hdl_umapdb_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EAGAIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hr_indx = rsrcp->hr_indx;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Allocate an entry to track the UAR page resource in the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "userland resources database".
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor umapdb = hermon_umap_db_alloc(instance, key,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor MLNX_UMAP_UARPG_RSRC, (uint64_t)(uintptr_t)rsrcp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (umapdb == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&hermon_userland_rsrc_db.hdl_umapdb_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* If in "maintenance mode", don't free the rsrc */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (HERMON_IS_OPERATIONAL(state->hs_operational_mode)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_free(state, &rsrcp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EAGAIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Create a new device number. Minor number is a function of
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the UAR page index (15 bits) and the device instance number
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (3 bits).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dev = makedevice(getmajor(*devp), (hr_indx <<
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_MINORNUM_SHIFT) | instance);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Allocate another entry in the "userland resources database"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to track the association of the device number (above) to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the current process ID (in "key").
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor umapdb2 = hermon_umap_db_alloc(instance, dev,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor MLNX_UMAP_PID_RSRC, (uint64_t)key);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (umapdb2 == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&hermon_userland_rsrc_db.hdl_umapdb_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_umap_db_free(umapdb);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* If in "maintenance mode", don't free the rsrc */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (HERMON_IS_OPERATIONAL(state->hs_operational_mode)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_free(state, &rsrcp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (EAGAIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Add the entries to the database */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_umap_db_add_nolock(umapdb);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_umap_db_add_nolock(umapdb2);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Return the same device number as on the original open()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * call. This was calculated as a function of the UAR page
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * index (top 16 bits) and the device instance number
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor rsrcp = (hermon_rsrc_t *)(uintptr_t)value;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dev = makedevice(getmajor(*devp), (rsrcp->hr_indx <<
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_MINORNUM_SHIFT) | instance);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&hermon_userland_rsrc_db.hdl_umapdb_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *devp = dev;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_close()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* ARGSUSED */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_close(dev_t dev, int flag, int otyp, cred_t *credp)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_state_t *state;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_t *rsrcp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_umap_db_entry_t *umapdb;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_umap_db_priv_t *priv;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor minor_t instance;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t key, value;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status, reset_status = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor instance = HERMON_DEV_INSTANCE(dev);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state = ddi_get_soft_state(hermon_statep, instance);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (ENXIO);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Search for "dev_t" in the "userland resources database". As
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * explained above in hermon_open(), we can't depend on using the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * current process ID here to do the lookup because the process
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that ultimately closes may not be the same one who opened
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (because of inheritance).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * So we lookup the "dev_t" (which points to the PID of the process
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that opened), and we remove the entry from the database (and free
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * it up). Then we do another query based on the PID value. And when
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * we find that database entry, we free it up too and then free the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Hermon UAR page resource.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: We use the hermon_umap_db_find_nolock() database access
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * routine below (with an explicit mutex_enter of the database lock)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to ensure that the multiple accesses (which attempt to remove the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * two database entries) can be done atomically.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * This works the same in both maintenance mode and HCA mode, except
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * for the call to hermon_rsrc_free(). In the case of maintenance mode,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * this call is not needed, as it was not allocated in hermon_open()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * above.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor key = dev;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&hermon_userland_rsrc_db.hdl_umapdb_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_umap_db_find_nolock(instance, key, MLNX_UMAP_PID_RSRC,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &value, HERMON_UMAP_DB_REMOVE, &umapdb);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status == DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If the "hdb_priv" field is non-NULL, it indicates that
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * some "on close" handling is still necessary. Call
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_umap_db_handle_onclose_cb() to do the handling (i.e.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to invoke all the registered callbacks). Then free up
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the resources associated with "hdb_priv" and continue
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * closing.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor priv = (hermon_umap_db_priv_t *)umapdb->hdbe_common.hdb_priv;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (priv != NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor reset_status = hermon_umap_db_handle_onclose_cb(priv);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(priv, sizeof (hermon_umap_db_priv_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor umapdb->hdbe_common.hdb_priv = (void *)NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_umap_db_free(umapdb);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Now do another lookup using PID as the key (copy it from
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "value"). When this lookup is complete, the "value" field
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * will contain the hermon_rsrc_t pointer for the UAR page
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * resource.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor key = value;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_umap_db_find_nolock(instance, key,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor MLNX_UMAP_UARPG_RSRC, &value, HERMON_UMAP_DB_REMOVE,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &umapdb);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status == DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_umap_db_free(umapdb);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* If in "maintenance mode", don't free the rsrc */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (HERMON_IS_OPERATIONAL(state->hs_operational_mode)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor rsrcp = (hermon_rsrc_t *)(uintptr_t)value;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_free(state, &rsrcp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&hermon_userland_rsrc_db.hdl_umapdb_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (reset_status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_attach()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_state_t *state;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibc_clnt_hdl_t tmp_ibtfpriv;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibc_status_t ibc_status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int instance;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef __lock_lint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_quiesce(dip);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (cmd) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case DDI_ATTACH:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor instance = ddi_get_instance(dip);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_soft_state_zalloc(hermon_statep, instance);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "hermon%d: driver failed to attach: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "attach_ssz_fail", instance);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto fail_attach_nomsg;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state = ddi_get_soft_state(hermon_statep, instance);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_soft_state_free(hermon_statep, instance);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "hermon%d: driver failed to attach: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "attach_gss_fail", instance);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto fail_attach_nomsg;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* clear the attach error buffer */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG_INIT(state->hs_attach_buf);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Save away devinfo and instance before hermon_fm_init() */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_dip = dip;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_instance = instance;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_init(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Initialize Hermon driver and hardware.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: If this initialization fails we may still wish to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * create a device node and remain operational so that Hermon
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * firmware can be updated/flashed (i.e. "maintenance mode").
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If this is the case, then "hs_operational_mode" will be
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * equal to HERMON_MAINTENANCE_MODE. We will not attempt to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * attach to the IBTF or register with the IBMF (i.e. no
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * InfiniBand interfaces will be enabled).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_drv_init(state, dip, instance);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((status != DDI_SUCCESS) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (HERMON_IS_OPERATIONAL(state->hs_operational_mode))) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto fail_attach;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Change the Hermon FM mode
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((hermon_get_state(state) & HCA_PIO_FM) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_IS_OPERATIONAL(state->hs_operational_mode)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Now we wait for 50ms to give an opportunity
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to Solaris FMA so that HW errors can be notified.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Then check if there are HW errors or not. If
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * a HW error is detected, the Hermon attachment
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * must be failed.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor delay(drv_usectohz(50000));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_init_failure(state)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_drv_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WARNING(state, "unable to "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "attach Hermon due to a HW error");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hermon_attach_failure");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto fail_attach;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * There seems no HW errors during the attachment,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * so let's change the Hermon FM state to the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * ereport only mode.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_fm_ereport_init(state) != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* unwind the resources */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_drv_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hermon_attach_failure");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto fail_attach;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Create the minor node for device */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_create_minor_node(dip, "devctl", S_IFCHR, instance,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor DDI_PSEUDO, 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_drv_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "attach_create_mn_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto fail_attach;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If we are in "maintenance mode", then we don't want to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * register with the IBTF. All InfiniBand interfaces are
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * uninitialized, and the device is only capable of handling
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * requests to update/flash firmware (or test/debug requests).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (HERMON_IS_OPERATIONAL(state->hs_operational_mode)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "!Hermon is operational\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Attach to InfiniBand Transport Framework (IBTF) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibc_status = ibc_attach(&tmp_ibtfpriv,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_ibtfinfo);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ibc_status != IBC_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "hermon_attach: ibc_attach "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "failed\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_remove_minor_node(dip, "devctl");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_drv_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "attach_ibcattach_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto fail_attach;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Now that we've successfully attached to the IBTF,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * we enable all appropriate asynch and CQ events to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * be forwarded to the IBTF.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ENABLE_IBTF_CALLB(state, tmp_ibtfpriv);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibc_post_attach(state->hs_ibtfpriv);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Register agents with IB Mgmt Framework (IBMF) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_agent_handlers_init(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) ibc_pre_detach(tmp_ibtfpriv, DDI_DETACH);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_QUIESCE_IBTF_CALLB(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_in_evcallb != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WARNING(state, "unable to "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "quiesce Hermon IBTF callbacks");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibc_detach(tmp_ibtfpriv);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_remove_minor_node(dip, "devctl");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_drv_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "attach_agentinit_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto fail_attach;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Report attach in maintenance mode, if appropriate */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (!(HERMON_IS_OPERATIONAL(state->hs_operational_mode))) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "hermon%d: driver attached "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "(for maintenance mode only)", state->hs_instance);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_IBA_ERR, HCA_ERR_DEGRADED);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Report that driver was loaded */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_report_dev(dip);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Send device information to log file */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_device_info_report(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* DEBUG PRINT */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "!Hermon attach complete\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case DDI_RESUME:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Add code here for DDI_RESUME XXX */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_WARN, "hermon_attach: unknown cmd (0x%x)\n", cmd);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorfail_attach:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "hermon%d: driver failed to attach: %s", instance,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_attach_buf);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_get_state(state) & HCA_EREPORT_FM) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_SRV_LOST);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
e99353559fac68ede91471daee91660d64cc7894Eiji Ota hermon_drv_fini2(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_soft_state_free(hermon_statep, instance);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorfail_attach_nomsg:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_detach()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from detach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_state_t *state;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibc_clnt_hdl_t tmp_ibtfpriv;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibc_status_t ibc_status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int instance, status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor instance = ddi_get_instance(dip);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state = ddi_get_soft_state(hermon_statep, instance);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state == NULL) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (cmd) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case DDI_DETACH:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If we are in "maintenance mode", then we do not want to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * do teardown for any of the InfiniBand interfaces.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Specifically, this means not detaching from IBTF (we never
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * attached to begin with) and not deregistering from IBMF.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (HERMON_IS_OPERATIONAL(state->hs_operational_mode)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Unregister agents from IB Mgmt Framework (IBMF) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_agent_handlers_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Attempt the "pre-detach" from InfiniBand Transport
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Framework (IBTF). At this point the IBTF is still
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * capable of handling incoming asynch and completion
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * events. This "pre-detach" is primarily a mechanism
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to notify the appropriate IBTF clients that the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * HCA is being removed/offlined.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibc_status = ibc_pre_detach(state->hs_ibtfpriv, cmd);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ibc_status != IBC_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_agent_handlers_init(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WARNING(state, "failed to "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "restart Hermon agents");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Before we can fully detach from the IBTF we need to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * ensure that we have handled all outstanding event
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * callbacks. This is accomplished by quiescing the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * event callback mechanism. Note: if we are unable
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to successfully quiesce the callbacks, then this is
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * an indication that something has probably gone
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * seriously wrong. We print out a warning, but
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * continue.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tmp_ibtfpriv = state->hs_ibtfpriv;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_QUIESCE_IBTF_CALLB(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_in_evcallb != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WARNING(state, "unable to quiesce "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "Hermon IBTF callbacks");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Complete the detach from the IBTF */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibc_detach(tmp_ibtfpriv);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Remove the minor node for device */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_remove_minor_node(dip, "devctl");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Only call hermon_drv_fini() if we are in Hermon HCA mode.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (Because if we are in "maintenance mode", then we never
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * successfully finished init.) Only report successful
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * detach for normal HCA mode.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (HERMON_IS_OPERATIONAL(state->hs_operational_mode)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Cleanup driver resources and shutdown hardware */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_drv_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "!Hermon driver successfully "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "detached\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_drv_fini2(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_soft_state_free(hermon_statep, instance);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case DDI_SUSPEND:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Add code here for DDI_SUSPEND XXX */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_WARN, "hermon_detach: unknown cmd (0x%x)\n", cmd);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_dma_attr_init()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from interrupt or base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* ARGSUSED */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorvoid
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_dma_attr_init(hermon_state_t *state, ddi_dma_attr_t *dma_attr)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dma_attr))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_version = DMA_ATTR_V0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_addr_lo = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_addr_hi = 0xFFFFFFFFFFFFFFFFull;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_count_max = 0xFFFFFFFFFFFFFFFFull;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_align = HERMON_PAGESIZE; /* default 4K */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_burstsizes = 0x3FF;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_minxfer = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_maxxfer = 0xFFFFFFFFFFFFFFFFull;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_seg = 0xFFFFFFFFFFFFFFFFull;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_sgllen = 0x7FFFFFFF;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_granular = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_attr->dma_attr_flags = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_dma_alloc()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_dma_alloc(hermon_state_t *state, hermon_dma_info_t *dma_info,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint16_t opcode)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_dma_handle_t dma_hdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_dma_attr_t dma_attr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t acc_hdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_dma_cookie_t cookie;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t kaddr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t real_len;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t ccount;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_dma_attr_init(state, &dma_attr);
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor#ifdef __sparc
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor if (state->hs_cfg_profile->cp_iommu_bypass == HERMON_BINDMEM_BYPASS)
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor dma_attr.dma_attr_flags = DDI_DMA_FORCE_PHYSICAL;
c7facc54c4abed9e554ff80225311e6b7048d3c9Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate a DMA handle */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_dma_alloc_handle(state->hs_dip, &dma_attr, DDI_DMA_SLEEP,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor NULL, &dma_hdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBTF_DPRINTF_L2("DMA", "alloc handle failed: %d", status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "DMA alloc handle failed(status %d)", status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate DMA memory */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_dma_mem_alloc(dma_hdl, dma_info->length,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_reg_accattr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (caddr_t *)&kaddr, (size_t *)&real_len, &acc_hdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_dma_free_handle(&dma_hdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBTF_DPRINTF_L2("DMA", "memory alloc failed: %d", status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "DMA memory alloc failed(status %d)", status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero((caddr_t)(uintptr_t)kaddr, real_len);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Bind the memory to the handle */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_dma_addr_bind_handle(dma_hdl, NULL,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (caddr_t)(uintptr_t)kaddr, (size_t)real_len, DDI_DMA_RDWR |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, NULL, &cookie, &ccount);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_dma_mem_free(&acc_hdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_dma_free_handle(&dma_hdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBTF_DPRINTF_L2("DMA", "bind handle failed: %d", status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "DMA bind handle failed(status %d)", status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Package the hermon_dma_info contents and return */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_info->vaddr = kaddr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_info->dma_hdl = dma_hdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_info->acc_hdl = acc_hdl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Pass the mapping information to the firmware */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_map_cmd_post(state, dma_info, opcode, cookie, ccount);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor char *s;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_dma_free(dma_info);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (opcode) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case MAP_ICM:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor s = "MAP_ICM";
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case MAP_FA:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor s = "MAP_FA";
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case MAP_ICM_AUX:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor s = "MAP_ICM_AUX";
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor s = "UNKNOWN";
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "Map cmd '%s' failed, status %08x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor s, status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_dma_free()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorvoid
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_dma_free(hermon_dma_info_t *info)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Unbind the handles and free the memory */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) ddi_dma_unbind_handle(info->dma_hdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_dma_mem_free(&info->acc_hdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_dma_free_handle(&info->dma_hdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* These macros are valid for use only in hermon_icm_alloc/hermon_icm_free. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#define HERMON_ICM_ALLOC(rsrc) \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_icm_alloc(state, rsrc, index1, index2)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#define HERMON_ICM_FREE(rsrc) \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_icm_free(state, rsrc, index1, index2)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_icm_alloc()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Only one thread can be here for a given hermon_rsrc_type_t "type".
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor *
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * "num_to_hdl" is set if there is a need for lookups from resource
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * number/index to resource handle. This is needed for QPs/CQs/SRQs
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * for the various affiliated events/errors.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorint
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_icm_alloc(hermon_state_t *state, hermon_rsrc_type_t type,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t index1, uint32_t index2)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_icm_table_t *icm;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_dma_info_t *dma_info;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint8_t *bitmap;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor int num_to_hdl = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_verbose) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBTF_DPRINTF_L2("hermon", "hermon_icm_alloc: rsrc_type (0x%x) "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "index1/2 (0x%x/0x%x)", type, index1, index2);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm = &state->hs_icm[type];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (type) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_QPC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = HERMON_ICM_ALLOC(HERMON_CMPT_QPC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = HERMON_ICM_ALLOC(HERMON_RDB);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) { /* undo icm_alloc's */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ICM_FREE(HERMON_CMPT_QPC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = HERMON_ICM_ALLOC(HERMON_ALTC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) { /* undo icm_alloc's */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ICM_FREE(HERMON_RDB);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ICM_FREE(HERMON_CMPT_QPC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = HERMON_ICM_ALLOC(HERMON_AUXC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) { /* undo icm_alloc's */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ICM_FREE(HERMON_ALTC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ICM_FREE(HERMON_RDB);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ICM_FREE(HERMON_CMPT_QPC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor num_to_hdl = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_SRQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = HERMON_ICM_ALLOC(HERMON_CMPT_SRQC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor num_to_hdl = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = HERMON_ICM_ALLOC(HERMON_CMPT_CQC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor num_to_hdl = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_EQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = HERMON_ICM_ALLOC(HERMON_CMPT_EQC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) { /* undo icm_alloc's */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* ensure existence of bitmap and dmainfo, sets "dma_info" */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_bitmap(bitmap, dma_info, icm, index1, num_to_hdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set up the DMA handle for allocation and mapping */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor dma_info += index2;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor _NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*dma_info))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_info->length = icm->span << icm->log_object_size;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_info->icmaddr = icm->icm_baseaddr +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (((index1 << icm->split_shift) +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (index2 << icm->span_shift)) << icm->log_object_size);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor /* Allocate memory for the num_to_qp/cq/srq pointers */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (num_to_hdl)
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor icm->num_to_hdl[index1][index2] =
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor kmem_zalloc(HERMON_ICM_SPAN * sizeof (void *), KM_SLEEP);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_verbose) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBTF_DPRINTF_L2("hermon", "alloc DMA: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "rsrc (0x%x) index (%x, %x) "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "icm_addr/len (%llx/%x) bitmap %p", type, index1, index2,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (longlong_t)dma_info->icmaddr, dma_info->length, bitmap);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate and map memory for this span */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_dma_alloc(state, dma_info, MAP_ICM);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBTF_DPRINTF_L2("hermon", "hermon_icm_alloc: DMA "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "allocation failed, status 0x%x", status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (type) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_QPC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ICM_FREE(HERMON_AUXC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ICM_FREE(HERMON_ALTC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ICM_FREE(HERMON_RDB);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ICM_FREE(HERMON_CMPT_QPC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_SRQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ICM_FREE(HERMON_CMPT_SRQC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ICM_FREE(HERMON_CMPT_CQC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_EQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ICM_FREE(HERMON_CMPT_EQC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_verbose) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBTF_DPRINTF_L2("hermon", "hermon_icm_alloc: mapping ICM: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "rsrc_type (0x%x) index (0x%x, 0x%x) alloc length (0x%x) "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "icm_addr (0x%lx)", type, index1, index2, dma_info->length,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_info->icmaddr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set the bit for this slot in the table bitmap */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_BMAP_BIT_SET(icm->icm_bitmap[index1], index2);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_icm_free()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Can be called from base context.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * ICM resources have been successfully returned from hermon_icm_alloc().
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Associated dma_info is no longer in use. Free the ICM backing memory.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorvoid
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_icm_free(hermon_state_t *state, hermon_rsrc_type_t type,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t index1, uint32_t index2)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_icm_table_t *icm;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_dma_info_t *dma_info;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm = &state->hs_icm[type];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(icm->icm_dma[index1][index2].icm_refcnt == 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_verbose) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBTF_DPRINTF_L2("hermon", "hermon_icm_free: rsrc_type (0x%x) "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "index (0x%x, 0x%x)", type, index1, index2);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_info = icm->icm_dma[index1] + index2;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* The following only happens if attach() is failing. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (dma_info == NULL)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Unmap the ICM allocation, then free the backing DMA memory */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_unmap_icm_cmd_post(state, dma_info);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WARNING(state, "UNMAP_ICM failure");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_dma_free(dma_info);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Clear the bit in the ICM table bitmap */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_BMAP_BIT_CLR(icm->icm_bitmap[index1], index2);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (type) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_QPC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ICM_FREE(HERMON_AUXC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ICM_FREE(HERMON_ALTC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ICM_FREE(HERMON_RDB);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ICM_FREE(HERMON_CMPT_QPC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_SRQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ICM_FREE(HERMON_CMPT_SRQC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ICM_FREE(HERMON_CMPT_CQC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_EQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ICM_FREE(HERMON_CMPT_EQC);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor/*
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * hermon_icm_num_to_hdl()
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * Context: Can be called from base or interrupt context.
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor *
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * Given an index of a resource, index through the sparsely allocated
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * arrays to find the pointer to its software handle. Return NULL if
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * any of the arrays of pointers has been freed (should never happen).
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylorvoid *
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylorhermon_icm_num_to_hdl(hermon_state_t *state, hermon_rsrc_type_t type,
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor uint32_t idx)
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor{
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_icm_table_t *icm;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor uint32_t span_offset;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor uint32_t index1, index2;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor void ***p1, **p2;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor icm = &state->hs_icm[type];
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_index(index1, index2, idx, icm, span_offset);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor p1 = icm->num_to_hdl[index1];
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (p1 == NULL) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor IBTF_DPRINTF_L2("hermon", "icm_num_to_hdl failed at level 1"
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor ": rsrc_type %d, index 0x%x", type, idx);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor return (NULL);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor p2 = p1[index2];
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (p2 == NULL) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor IBTF_DPRINTF_L2("hermon", "icm_num_to_hdl failed at level 2"
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor ": rsrc_type %d, index 0x%x", type, idx);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor return (NULL);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor return (p2[span_offset]);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor}
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor/*
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * hermon_icm_set_num_to_hdl()
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * Context: Can be called from base or interrupt context.
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor *
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * Given an index of a resource, we index through the sparsely allocated
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * arrays to store the software handle, used by hermon_icm_num_to_hdl().
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * This function is used to both set and reset (set to NULL) the handle.
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * This table is allocated during ICM allocation for the given resource,
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * so its existence is a given, and the store location does not conflict
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * with any other stores to the table (no locking needed).
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylorvoid
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylorhermon_icm_set_num_to_hdl(hermon_state_t *state, hermon_rsrc_type_t type,
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor uint32_t idx, void *hdl)
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor{
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_icm_table_t *icm;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor uint32_t span_offset;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor uint32_t index1, index2;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor icm = &state->hs_icm[type];
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_index(index1, index2, idx, icm, span_offset);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor ASSERT((hdl == NULL) ^
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor (icm->num_to_hdl[index1][index2][span_offset] == NULL));
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor icm->num_to_hdl[index1][index2][span_offset] = hdl;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor}
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor/*
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor * hermon_device_mode()
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor * Context: Can be called from base or interrupt context.
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor *
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor * Return HERMON_HCA_MODE for operational mode
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor * Return HERMON_MAINTENANCE_MODE for maintenance mode
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor * Return 0 otherwise
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor *
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor * A non-zero return for either operational or maintenance mode simplifies
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor * one of the 2 uses of this function.
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor */
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylorint
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylorhermon_device_mode(hermon_state_t *state)
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor{
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor if (state->hs_vendor_id != PCI_VENID_MLX)
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor return (0);
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor switch (state->hs_device_id) {
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor case PCI_DEVID_HERMON_SDR:
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor case PCI_DEVID_HERMON_DDR:
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor case PCI_DEVID_HERMON_DDRG2:
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor case PCI_DEVID_HERMON_QDRG2:
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor case PCI_DEVID_HERMON_QDRG2V:
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor return (HERMON_HCA_MODE);
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor case PCI_DEVID_HERMON_MAINT:
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor return (HERMON_MAINTENANCE_MODE);
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor default:
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor return (0);
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor }
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor}
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_drv_init()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* ARGSUSED */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_drv_init(hermon_state_t *state, dev_info_t *dip, int instance)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor /* Retrieve PCI device, vendor and rev IDs */
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor state->hs_vendor_id = HERMON_GET_VENDOR_ID(state->hs_dip);
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor state->hs_device_id = HERMON_GET_DEVICE_ID(state->hs_dip);
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor state->hs_revision_id = HERMON_GET_REVISION_ID(state->hs_dip);
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check and set the operational mode of the device. If the driver is
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * bound to the Hermon device in "maintenance mode", then this generally
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * means that either the device has been specifically jumpered to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * start in this mode or the firmware boot process has failed to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * successfully load either the primary or the secondary firmware
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * image.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor state->hs_operational_mode = hermon_device_mode(state);
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor switch (state->hs_operational_mode) {
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor case HERMON_HCA_MODE:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_cfg_profile_setting = HERMON_CFG_MEMFREE;
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor break;
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor case HERMON_MAINTENANCE_MODE:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_FMANOTE(state, HERMON_FMA_MAINT);
32c5adfd7396fc0a0807a6f8cbb3a257e4c27af2Eiji Ota state->hs_fm_degraded_reason = HCA_FW_MISC; /* not fw reason */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_FMANOTE(state, HERMON_FMA_PCIID);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WARNING(state, "unexpected device type detected");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Initialize the Hermon hardware.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Note: If this routine returns an error, it is often a reasonably
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * good indication that something Hermon firmware-related has caused
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the failure or some HW related errors have caused the failure.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (also there are few possibilities that SW (e.g. SW resource
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * shortage) can cause the failure, but the majority case is due to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * either a firmware related error or a HW related one) In order to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * give the user an opportunity (if desired) to update or reflash
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the Hermon firmware image, we set "hs_operational_mode" flag
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (described above) to indicate that we wish to enter maintenance
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * mode in case of the firmware-related issue.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_hw_init(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "hermon%d: error during attach: %s", instance,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_attach_buf);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Now that the ISR has been setup, arm all the EQs for event
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * generation.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_eq_arm_all(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "EQ Arm All failed\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, HERMON_DRV_CLEANUP_ALL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* test interrupts and event queues */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_nop_post(state, 0x0, 0x0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "Interrupts/EQs failed\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, HERMON_DRV_CLEANUP_ALL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize Hermon softstate */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_soft_state_init(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "Failed to init soft state\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, HERMON_DRV_CLEANUP_ALL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_drv_fini()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() and/or detach() path contexts
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_drv_fini(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Cleanup Hermon softstate */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_soft_state_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Cleanup Hermon resources and shutdown hardware */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, HERMON_DRV_CLEANUP_ALL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_drv_fini2()
e99353559fac68ede91471daee91660d64cc7894Eiji Ota * Context: Only called from attach() and/or detach() path contexts
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_drv_fini2(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_fm_poll_thread) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_periodic_delete(state->hs_fm_poll_thread);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fm_poll_thread = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
e99353559fac68ede91471daee91660d64cc7894Eiji Ota
e99353559fac68ede91471daee91660d64cc7894Eiji Ota /* HERMON_DRV_CLEANUP_LEVEL1 */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_fm_cmdhdl) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_regs_map_free(state, &state->hs_fm_cmdhdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fm_cmdhdl = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
e99353559fac68ede91471daee91660d64cc7894Eiji Ota
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_reg_cmdhdl) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_regs_map_free(&state->hs_reg_cmdhdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_reg_cmdhdl = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
e99353559fac68ede91471daee91660d64cc7894Eiji Ota
e99353559fac68ede91471daee91660d64cc7894Eiji Ota /* HERMON_DRV_CLEANUP_LEVEL0 */
e99353559fac68ede91471daee91660d64cc7894Eiji Ota if (state->hs_msix_tbl_entries) {
e99353559fac68ede91471daee91660d64cc7894Eiji Ota kmem_free(state->hs_msix_tbl_entries,
e99353559fac68ede91471daee91660d64cc7894Eiji Ota state->hs_msix_tbl_size);
e99353559fac68ede91471daee91660d64cc7894Eiji Ota state->hs_msix_tbl_entries = NULL;
e99353559fac68ede91471daee91660d64cc7894Eiji Ota }
e99353559fac68ede91471daee91660d64cc7894Eiji Ota
e99353559fac68ede91471daee91660d64cc7894Eiji Ota if (state->hs_msix_pba_entries) {
e99353559fac68ede91471daee91660d64cc7894Eiji Ota kmem_free(state->hs_msix_pba_entries,
e99353559fac68ede91471daee91660d64cc7894Eiji Ota state->hs_msix_pba_size);
e99353559fac68ede91471daee91660d64cc7894Eiji Ota state->hs_msix_pba_entries = NULL;
e99353559fac68ede91471daee91660d64cc7894Eiji Ota }
e99353559fac68ede91471daee91660d64cc7894Eiji Ota
e99353559fac68ede91471daee91660d64cc7894Eiji Ota if (state->hs_fm_msix_tblhdl) {
e99353559fac68ede91471daee91660d64cc7894Eiji Ota hermon_regs_map_free(state, &state->hs_fm_msix_tblhdl);
e99353559fac68ede91471daee91660d64cc7894Eiji Ota state->hs_fm_msix_tblhdl = NULL;
e99353559fac68ede91471daee91660d64cc7894Eiji Ota }
e99353559fac68ede91471daee91660d64cc7894Eiji Ota
e99353559fac68ede91471daee91660d64cc7894Eiji Ota if (state->hs_reg_msix_tblhdl) {
e99353559fac68ede91471daee91660d64cc7894Eiji Ota ddi_regs_map_free(&state->hs_reg_msix_tblhdl);
e99353559fac68ede91471daee91660d64cc7894Eiji Ota state->hs_reg_msix_tblhdl = NULL;
e99353559fac68ede91471daee91660d64cc7894Eiji Ota }
e99353559fac68ede91471daee91660d64cc7894Eiji Ota
e99353559fac68ede91471daee91660d64cc7894Eiji Ota if (state->hs_fm_msix_pbahdl) {
e99353559fac68ede91471daee91660d64cc7894Eiji Ota hermon_regs_map_free(state, &state->hs_fm_msix_pbahdl);
e99353559fac68ede91471daee91660d64cc7894Eiji Ota state->hs_fm_msix_pbahdl = NULL;
e99353559fac68ede91471daee91660d64cc7894Eiji Ota }
e99353559fac68ede91471daee91660d64cc7894Eiji Ota
e99353559fac68ede91471daee91660d64cc7894Eiji Ota if (state->hs_reg_msix_pbahdl) {
e99353559fac68ede91471daee91660d64cc7894Eiji Ota ddi_regs_map_free(&state->hs_reg_msix_pbahdl);
e99353559fac68ede91471daee91660d64cc7894Eiji Ota state->hs_reg_msix_pbahdl = NULL;
e99353559fac68ede91471daee91660d64cc7894Eiji Ota }
e99353559fac68ede91471daee91660d64cc7894Eiji Ota
e99353559fac68ede91471daee91660d64cc7894Eiji Ota if (state->hs_fm_pcihdl) {
e99353559fac68ede91471daee91660d64cc7894Eiji Ota hermon_pci_config_teardown(state, &state->hs_fm_pcihdl);
e99353559fac68ede91471daee91660d64cc7894Eiji Ota state->hs_fm_pcihdl = NULL;
e99353559fac68ede91471daee91660d64cc7894Eiji Ota }
e99353559fac68ede91471daee91660d64cc7894Eiji Ota
e99353559fac68ede91471daee91660d64cc7894Eiji Ota if (state->hs_reg_pcihdl) {
e99353559fac68ede91471daee91660d64cc7894Eiji Ota pci_config_teardown(&state->hs_reg_pcihdl);
e99353559fac68ede91471daee91660d64cc7894Eiji Ota state->hs_reg_pcihdl = NULL;
e99353559fac68ede91471daee91660d64cc7894Eiji Ota }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_isr_init()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_isr_init(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int intr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (intr = 0; intr < state->hs_intrmsi_allocd; intr++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Add a handler for the interrupt or MSI
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_intr_add_handler(state->hs_intrmsi_hdl[intr],
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_isr, (caddr_t)state, (void *)(uintptr_t)intr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Enable the software interrupt. Note: depending on the value
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * returned in the capability flag, we have to call either
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * ddi_intr_block_enable() or ddi_intr_enable().
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_intrmsi_cap & DDI_INTR_FLAG_BLOCK) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_intr_block_enable(
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_intrmsi_hdl[intr], 1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_intr_enable(state->hs_intrmsi_hdl[intr]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Now that the ISR has been enabled, defer arm_all EQs for event
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * generation until later, in case MSIX is enabled
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_isr_fini()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() and/or detach() path contexts
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_isr_fini(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int intr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (intr = 0; intr < state->hs_intrmsi_allocd; intr++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Disable the software interrupt */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_intrmsi_cap & DDI_INTR_FLAG_BLOCK) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) ddi_intr_block_disable(
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_intrmsi_hdl[intr], 1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) ddi_intr_disable(state->hs_intrmsi_hdl[intr]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Remove the software handler for the interrupt or MSI
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) ddi_intr_remove_handler(state->hs_intrmsi_hdl[intr]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Sum of ICM configured values:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * cMPT, dMPT, MTT, QPC, SRQC, RDB, CQC, ALTC, AUXC, EQC, MCG
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic uint64_t
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_size_icm(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_querydevlim_t *devlim;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_cfg_profile_t *cfg;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t num_cmpts, num_dmpts, num_mtts;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t num_qpcs, num_srqc, num_rdbs;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifndef HERMON_FW_WORKAROUND
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t num_auxc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t num_cqcs, num_altc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t num_eqcs, num_mcgs;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t size;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor devlim = &state->hs_devlim;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cfg = state->hs_cfg_profile;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* number of respective entries */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_cmpts = (uint64_t)0x1 << cfg->cp_log_num_cmpt;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_mtts = (uint64_t)0x1 << cfg->cp_log_num_mtt;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_dmpts = (uint64_t)0x1 << cfg->cp_log_num_dmpt;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_qpcs = (uint64_t)0x1 << cfg->cp_log_num_qp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_srqc = (uint64_t)0x1 << cfg->cp_log_num_srq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_rdbs = (uint64_t)0x1 << cfg->cp_log_num_rdb;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_cqcs = (uint64_t)0x1 << cfg->cp_log_num_cq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_altc = (uint64_t)0x1 << cfg->cp_log_num_qp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifndef HERMON_FW_WORKAROUND
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_auxc = (uint64_t)0x1 << cfg->cp_log_num_qp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_eqcs = (uint64_t)0x1 << cfg->cp_log_num_eq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_mcgs = (uint64_t)0x1 << cfg->cp_log_num_mcg;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor size =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_cmpts * devlim->cmpt_entry_sz +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_dmpts * devlim->dmpt_entry_sz +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_mtts * devlim->mtt_entry_sz +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_qpcs * devlim->qpc_entry_sz +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_srqc * devlim->srq_entry_sz +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_rdbs * devlim->rdmardc_entry_sz +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_cqcs * devlim->cqc_entry_sz +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_altc * devlim->altc_entry_sz +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef HERMON_FW_WORKAROUND
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor 0x80000000ull +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#else
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_auxc * devlim->aux_entry_sz +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_eqcs * devlim->eqc_entry_sz +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_mcgs * HERMON_MCGMEM_SZ(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (size);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_hw_init()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_hw_init(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_drv_cleanup_level_t cleanup;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sm_nodeinfo_t nodeinfo;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t clr_intr_offset;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t fw_size; /* in page */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t offset;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This is where driver initialization begins */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cleanup = HERMON_DRV_CLEANUP_LEVEL0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Setup device access attributes */
837c1ac4e72b7d86278cca88b1075af557f7d161Stephen Hanson state->hs_reg_accattr.devacc_attr_version = DDI_DEVICE_ATTR_V1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_reg_accattr.devacc_attr_endian_flags = DDI_STRUCTURE_BE_ACC;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_reg_accattr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_reg_accattr.devacc_attr_access = DDI_DEFAULT_ACC;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Setup fma-protected access attributes */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fm_accattr.devacc_attr_version =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_devacc_attr_version(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fm_accattr.devacc_attr_endian_flags = DDI_STRUCTURE_BE_ACC;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fm_accattr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* set acc err protection type */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fm_accattr.devacc_attr_access =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_devacc_attr_access(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Setup for PCI config read/write of HCA device */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_pci_config_setup(state, &state->hs_fm_pcihdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_PCI_config_space_regmap_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Map PCI config space and MSI-X tables/pba */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_set_msix_info(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Map in Hermon registers (CMD, UAR, MSIX) and setup offsets */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_regs_map_setup(state, HERMON_CMD_BAR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_reg_cmd_baseaddr, 0, 0, &state->hs_fm_accattr,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_fm_cmdhdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_CMD_BAR_regmap_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cleanup = HERMON_DRV_CLEANUP_LEVEL1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * We defer UAR-BAR mapping until later. Need to know if
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * blueflame mapping is to be done, and don't know that until after
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * we get the dev_caps, so do it right after that
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * There is a third BAR defined for Hermon - it is for MSIX
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Will need to explore it's possible need/use w/ Mellanox
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * [es] Temporary mapping maybe
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef HERMON_SUPPORTS_MSIX_BAR
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_regs_map_setup(state->hs_dip, HERMON_MSIX_BAR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_reg_msi_baseaddr, 0, 0, &state->hs_reg_accattr,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_reg_msihdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_MSIX_BAR_regmap_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cleanup = HERMON_DRV_CLEANUP_LEVEL2;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Save interesting registers away. The offsets of the first two
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * here (HCR and sw_reset) are detailed in the PRM, the others are
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * derived from values in the QUERY_FW output, so we'll save them
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * off later.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Host Command Register (HCR) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_cmd_regs.hcr = (hermon_hw_hcr_t *)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ((uintptr_t)state->hs_reg_cmd_baseaddr + HERMON_CMD_HCR_OFFSET);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_cmd_toggle = 0; /* initialize it for use */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Software Reset register (sw_reset) and semaphore */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_cmd_regs.sw_reset = (uint32_t *)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ((uintptr_t)state->hs_reg_cmd_baseaddr +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_CMD_SW_RESET_OFFSET);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_cmd_regs.sw_semaphore = (uint32_t *)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ((uintptr_t)state->hs_reg_cmd_baseaddr +
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_CMD_SW_SEMAPHORE_OFFSET);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* make sure init'd before we start filling things in */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(&state->hs_hcaparams, sizeof (struct hermon_hw_initqueryhca_s));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize the Phase1 configuration profile */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_cfg_profile_init_phase1(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_cfginit1_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cleanup = HERMON_DRV_CLEANUP_LEVEL3;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Do a software reset of the adapter to ensure proper state */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_sw_reset(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != HERMON_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_sw_reset_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize mailboxes */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_rsrc_init_phase1(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_rsrcinit1_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cleanup = HERMON_DRV_CLEANUP_LEVEL4;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Post QUERY_FW */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_cmn_query_cmd_post(state, QUERY_FW, 0, 0, &state->hs_fw,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_queryfw_t), HERMON_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != HERMON_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "QUERY_FW command failed: %08x\n", status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_query_fw_cmd_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Validate what/that HERMON FW version is appropriate */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_fw_version_check(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_FMANOTE(state, HERMON_FMA_FWVER);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_operational_mode == HERMON_HCA_MODE) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Unsupported Hermon FW version: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "expected: %04d.%04d.%04d, "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "actual: %04d.%04d.%04d\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_FW_VER_MAJOR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_FW_VER_MINOR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_FW_VER_SUBMINOR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw.fw_rev_major,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw.fw_rev_minor,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw.fw_rev_subminor);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Unsupported FW version: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "%04d.%04d.%04d\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw.fw_rev_major,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw.fw_rev_minor,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw.fw_rev_subminor);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_operational_mode = HERMON_MAINTENANCE_MODE;
32c5adfd7396fc0a0807a6f8cbb3a257e4c27af2Eiji Ota state->hs_fm_degraded_reason = HCA_FW_MISMATCH;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_checkfwver_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (HERMON_CMD_BAD_NVMEM);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Save off the rest of the interesting registers that we'll be using.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Setup the offsets for the other registers.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Hermon does the intr_offset from the BAR - technically should get the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * BAR info from the response, but PRM says it's from BAR0-1, which is
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * for us the CMD BAR
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor clr_intr_offset = state->hs_fw.clr_intr_offs & HERMON_CMD_OFFSET_MASK;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Save Clear Interrupt address */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_cmd_regs.clr_intr = (uint64_t *)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uintptr_t)(state->hs_reg_cmd_baseaddr + clr_intr_offset);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Set the error buffer also into the structure - used in hermon_event.c
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to check for internal error on the HCA, not reported in eqe or
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (necessarily) by interrupt
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_cmd_regs.fw_err_buf = (uint32_t *)(uintptr_t)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (state->hs_reg_cmd_baseaddr + state->hs_fw.error_buf_addr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Invoke a polling thread to check the error buffer periodically.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
332f545bce1434913a4e2bffd942656ef0906846Eiji Ota if (!hermon_no_inter_err_chk) {
332f545bce1434913a4e2bffd942656ef0906846Eiji Ota state->hs_fm_poll_thread = ddi_periodic_add(
332f545bce1434913a4e2bffd942656ef0906846Eiji Ota hermon_inter_err_chk, (void *)state, FM_POLL_INTERVAL,
332f545bce1434913a4e2bffd942656ef0906846Eiji Ota DDI_IPL_0);
332f545bce1434913a4e2bffd942656ef0906846Eiji Ota }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cleanup = HERMON_DRV_CLEANUP_LEVEL5;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Allocate, map, and run the HCA Firmware.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate memory for the firmware to load into and map it */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* get next higher power of 2 */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fw_size = 1 << highbit(state->hs_fw.fw_pages);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_dma.length = fw_size << HERMON_PAGESHIFT;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_dma_alloc(state, &state->hs_fw_dma, MAP_FA);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "FW alloc failed\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_dma_alloc_fw_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cleanup = HERMON_DRV_CLEANUP_LEVEL6;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Invoke the RUN_FW cmd to run the firmware */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_run_fw_cmd_post(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "RUN_FW command failed: 0x%08x\n", status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status == HERMON_CMD_BAD_NVMEM) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_operational_mode = HERMON_MAINTENANCE_MODE;
32c5adfd7396fc0a0807a6f8cbb3a257e4c27af2Eiji Ota state->hs_fm_degraded_reason = HCA_FW_CORRUPT;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf, "hw_init_run_fw_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If the status is HERMON_CMD_BAD_NVMEM, it's likely the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * firmware is corrupted, so the mode falls into the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * maintenance mode.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status == HERMON_CMD_BAD_NVMEM ? HERMON_CMD_BAD_NVMEM :
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * QUERY DEVICE LIMITS/CAPABILITIES
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * NOTE - in Hermon, the command is changed to QUERY_DEV_CAP,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * but for familiarity we have kept the structure name the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * same as Tavor/Arbel
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_cmn_query_cmd_post(state, QUERY_DEV_CAP, 0, 0,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_devlim, sizeof (hermon_hw_querydevlim_t),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != HERMON_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "QUERY_DEV_CAP command failed: 0x%08x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf, "hw_init_devcap_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor state->hs_rsvd_eqs = max(state->hs_devlim.num_rsvd_eq,
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor (4 * state->hs_devlim.num_rsvd_uar));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* now we have enough info to map in the UAR BAR */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * First, we figure out how to map the BAR for UAR - use only half if
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * BlueFlame is enabled - in that case the mapped length is 1/2 the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * log_max_uar_sz (max__uar - 1) * 1MB ( +20).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_devlim.blu_flm) { /* Blue Flame Enabled */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor offset = (uint64_t)1 << (state->hs_devlim.log_max_uar_sz + 20);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor offset = 0; /* a zero length means map the whole thing */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_regs_map_setup(state, HERMON_UAR_BAR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_reg_uar_baseaddr, 0, offset, &state->hs_fm_accattr,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_fm_uarhdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf, "UAR BAR mapping");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* and if BlueFlame is enabled, map the other half there */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_devlim.blu_flm) { /* Blue Flame Enabled */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor offset = (uint64_t)1 << (state->hs_devlim.log_max_uar_sz + 20);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_regs_map_setup(state->hs_dip, HERMON_UAR_BAR,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_reg_bf_baseaddr, offset, offset,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_reg_accattr, &state->hs_reg_bfhdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "BlueFlame BAR mapping");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This will be used in hw_fini if we fail to init. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_bf_offset = offset;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cleanup = HERMON_DRV_CLEANUP_LEVEL7;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Hermon has a couple of things needed for phase 2 in query port */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_cmn_query_cmd_post(state, QUERY_PORT, 0, 0x01,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_queryport, sizeof (hermon_hw_query_port_t),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != HERMON_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "QUERY_PORT command failed: 0x%08x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_queryport_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize the Phase2 Hermon configuration profile */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_cfg_profile_init_phase2(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "CFG phase 2 failed: 0x%08x\n", status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_cfginit2_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Determine and set the ICM size */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_icm_sz = hermon_size_icm(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_set_icm_size_cmd_post(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "Hermon: SET_ICM_SIZE cmd failed: 0x%08x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_seticmsz_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* alloc icm aux physical memory and map it */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_icma_dma.length = 1 << highbit(state->hs_icma_sz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_dma_alloc(state, &state->hs_icma_dma, MAP_ICM_AUX);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "failed to alloc (0x%llx) bytes for ICMA\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (longlong_t)state->hs_icma_dma.length);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_dma_alloc_icm_aux_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cleanup = HERMON_DRV_CLEANUP_LEVEL8;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cleanup = HERMON_DRV_CLEANUP_LEVEL9;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate an array of structures to house the ICM tables */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_icm = kmem_zalloc(HERMON_NUM_ICM_RESOURCES *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_icm_table_t), KM_SLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set up the ICM address space and the INIT_HCA command input */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_icm_config_setup(state, &state->hs_hcaparams);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != HERMON_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "ICM configuration failed\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_icm_config_setup_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cleanup = HERMON_DRV_CLEANUP_LEVEL10;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize the adapter with the INIT_HCA cmd */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_init_hca_cmd_post(state, &state->hs_hcaparams,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != HERMON_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "INIT_HCA command failed: %08x\n", status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf, "hw_init_hca_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cleanup = HERMON_DRV_CLEANUP_LEVEL11;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Enter the second phase of init for Hermon configuration/resources */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_rsrc_init_phase2(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_rsrcinit2_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cleanup = HERMON_DRV_CLEANUP_LEVEL12;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Query the adapter via QUERY_ADAPTER */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_cmn_query_cmd_post(state, QUERY_ADAPTER, 0, 0,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_adapter, sizeof (hermon_hw_queryadapter_t),
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != HERMON_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "Hermon: QUERY_ADAPTER command failed: %08x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_query_adapter_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate protection domain (PD) for Hermon internal use */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_pd_alloc(state, &state->hs_pdhdl_internal,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_SLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "failed to alloc internal PD\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_internal_pd_alloc_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cleanup = HERMON_DRV_CLEANUP_LEVEL13;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Setup UAR page for kernel use */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_internal_uarpg_init(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "failed to setup internal UAR\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_internal_uarpg_alloc_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cleanup = HERMON_DRV_CLEANUP_LEVEL14;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Query and initialize the Hermon interrupt/MSI information */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_intr_or_msi_init(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "failed to setup INTR/MSI\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_intr_or_msi_init_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cleanup = HERMON_DRV_CLEANUP_LEVEL15;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_isr_init(state); /* set up the isr */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "failed to init isr\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_isrinit_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cleanup = HERMON_DRV_CLEANUP_LEVEL16;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Setup the event queues */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_eq_init_all(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "failed to init EQs\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_eqinitall_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cleanup = HERMON_DRV_CLEANUP_LEVEL17;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Reserve contexts for QP0 and QP1 */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_special_qp_contexts_reserve(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "failed to init special QPs\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_rsrv_sqp_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cleanup = HERMON_DRV_CLEANUP_LEVEL18;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize for multicast group handling */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_mcg_init(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "failed to init multicast\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_mcg_init_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cleanup = HERMON_DRV_CLEANUP_LEVEL19;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize the Hermon IB port(s) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_hca_port_init(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "failed to init HCA Port\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_hca_port_init_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cleanup = HERMON_DRV_CLEANUP_ALL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Determine NodeGUID and SystemImageGUID */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_getnodeinfo_cmd_post(state, HERMON_CMD_NOSLEEP_SPIN,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &nodeinfo);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != HERMON_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "GetNodeInfo command failed: %08x\n", status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_getnodeinfo_cmd_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If the NodeGUID value was set in OBP properties, then we use that
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * value. But we still print a message if the value we queried from
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * firmware does not match this value.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Otherwise if OBP value is not set then we use the value from
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * firmware unconditionally.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_cfg_profile->cp_nodeguid) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_nodeguid = state->hs_cfg_profile->cp_nodeguid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_nodeguid = nodeinfo.NodeGUID;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_nodeguid != nodeinfo.NodeGUID) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "!NodeGUID value queried from firmware "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "does not match value set by device property");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If the SystemImageGUID value was set in OBP properties, then we use
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that value. But we still print a message if the value we queried
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * from firmware does not match this value.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Otherwise if OBP value is not set then we use the value from
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * firmware unconditionally.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_cfg_profile->cp_sysimgguid) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_sysimgguid = state->hs_cfg_profile->cp_sysimgguid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_sysimgguid = nodeinfo.SystemImageGUID;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_sysimgguid != nodeinfo.SystemImageGUID) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "!SystemImageGUID value queried from firmware "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "does not match value set by device property");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Get NodeDescription */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_getnodedesc_cmd_post(state, HERMON_CMD_NOSLEEP_SPIN,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (sm_nodedesc_t *)&state->hs_nodedesc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != HERMON_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "GetNodeDesc command failed: %08x\n", status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_fini(state, cleanup);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hw_init_getnodedesc_cmd_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* This case is not the degraded one */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_hw_fini()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() and/or detach() path contexts
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_hw_fini(hermon_state_t *state, hermon_drv_cleanup_level_t cleanup)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t num_ports;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i, status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * JBDB - We might not want to run these returns in all cases of
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Bad News. We should still attempt to free all of the DMA memory
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * resources... This needs to be worked last, after all allocations
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * are implemented. For now, and possibly for later, this works.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (cleanup) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If we add more driver initialization steps that should be cleaned
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * up here, we need to ensure that HERMON_DRV_CLEANUP_ALL is still the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * first entry (i.e. corresponds to the last init step).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DRV_CLEANUP_ALL:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Shutdown the Hermon IB port(s) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_ports = state->hs_cfg_profile->cp_num_ports;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_hca_ports_shutdown(state, num_ports);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DRV_CLEANUP_LEVEL19:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Teardown resources used for multicast group handling */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_mcg_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DRV_CLEANUP_LEVEL18:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Unreserve the special QP contexts */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_special_qp_contexts_unreserve(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DRV_CLEANUP_LEVEL17:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Attempt to teardown all event queues (EQ). If we fail
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * here then print a warning message and return. Something
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (either in HW or SW) has gone seriously wrong.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_eq_fini_all(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WARNING(state, "failed to teardown EQs");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DRV_CLEANUP_LEVEL16:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Teardown Hermon interrupts */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_isr_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DRV_CLEANUP_LEVEL15:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_intr_or_msi_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WARNING(state, "failed to free intr/MSI");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DRV_CLEANUP_LEVEL14:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the resources for the Hermon internal UAR pages */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_internal_uarpg_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DRV_CLEANUP_LEVEL13:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Free the PD that was used internally by Hermon software. If
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * we fail here then print a warning and return. Something
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (probably software-related, but perhaps HW) has gone wrong.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_pd_free(state, &state->hs_pdhdl_internal);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WARNING(state, "failed to free internal PD");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DRV_CLEANUP_LEVEL12:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Cleanup all the phase2 resources first */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_fini(state, HERMON_RSRC_CLEANUP_ALL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DRV_CLEANUP_LEVEL11:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* LEVEL11 is after INIT_HCA */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DRV_CLEANUP_LEVEL10:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Unmap the ICM memory area with UNMAP_ICM command.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_unmap_icm_cmd_post(state, NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_WARN,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hermon_hw_fini: failed to unmap ICM\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the initial ICM DMA handles */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_icm_dma_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the ICM table structures */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_icm_tables_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the ICM table handles */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(state->hs_icm, HERMON_NUM_ICM_RESOURCES *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_icm_table_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DRV_CLEANUP_LEVEL9:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Unmap the ICM Aux memory area with UNMAP_ICM_AUX command.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_unmap_icm_aux_cmd_post(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != HERMON_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hermon_hw_fini: failed to unmap ICMA\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DRV_CLEANUP_LEVEL8:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Deallocate ICM Aux DMA memory.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_dma_free(&state->hs_icma_dma);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DRV_CLEANUP_LEVEL7:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_fm_uarhdl) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_regs_map_free(state, &state->hs_fm_uarhdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fm_uarhdl = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_reg_uarhdl) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_regs_map_free(&state->hs_reg_uarhdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_reg_uarhdl = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_bf_offset != 0 && state->hs_reg_bfhdl) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_regs_map_free(&state->hs_reg_bfhdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_reg_bfhdl = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < HERMON_MAX_PORTS; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_pkey[i]) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(state->hs_pkey[i], (1 <<
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_cfg_profile->cp_log_max_pkeytbl) *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (ib_pkey_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_pkey[i] = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_guid[i]) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(state->hs_guid[i], (1 <<
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_cfg_profile->cp_log_max_gidtbl) *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (ib_guid_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_guid[i] = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DRV_CLEANUP_LEVEL6:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Unmap the firmware memory area with UNMAP_FA command.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_unmap_fa_cmd_post(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != HERMON_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "hermon_hw_fini: failed to unmap FW\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Deallocate firmware DMA memory.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_dma_free(&state->hs_fw_dma);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DRV_CLEANUP_LEVEL5:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* stop the poll thread */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_fm_poll_thread) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_periodic_delete(state->hs_fm_poll_thread);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fm_poll_thread = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DRV_CLEANUP_LEVEL4:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Then cleanup the phase1 resources */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_fini(state, HERMON_RSRC_CLEANUP_PHASE1_COMPLETE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DRV_CLEANUP_LEVEL3:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Teardown any resources allocated for the config profile */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_cfg_profile_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DRV_CLEANUP_LEVEL2:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef HERMON_SUPPORTS_MSIX_BAR
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * unmap 3rd BAR, MSIX BAR
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_reg_msihdl) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_regs_map_free(&state->hs_reg_msihdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_reg_msihdl = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DRV_CLEANUP_LEVEL1:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DRV_CLEANUP_LEVEL0:
e99353559fac68ede91471daee91660d64cc7894Eiji Ota /*
e99353559fac68ede91471daee91660d64cc7894Eiji Ota * LEVEL1 and LEVEL0 resources are freed in
e99353559fac68ede91471daee91660d64cc7894Eiji Ota * hermon_drv_fini2().
e99353559fac68ede91471daee91660d64cc7894Eiji Ota */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WARNING(state, "unexpected driver cleanup level");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_soft_state_init()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_soft_state_init(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_hca_attr_t *hca_attr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t maxval, val;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_hca_flags_t caps = IBT_HCA_NO_FLAGS;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ibt_hca_flags2_t caps2 = IBT_HCA2_NO_FLAGS;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int max_send_wqe_bytes;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int max_recv_wqe_bytes;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * The ibc_hca_info_t struct is passed to the IBTF. This is the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * routine where we initialize it. Many of the init values come from
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * either configuration variables or successful queries of the Hermon
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hardware abilities
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor state->hs_ibtfinfo.hca_ci_vers = IBCI_V4;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_ibtfinfo.hca_handle = (ibc_hca_hdl_t)state;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_ibtfinfo.hca_ops = &hermon_ibc_ops;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr = kmem_zalloc(sizeof (ibt_hca_attr_t), KM_SLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_ibtfinfo.hca_attr = hca_attr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hca_attr->hca_dip = state->hs_dip;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_fw_major_version = state->hs_fw.fw_rev_major;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_fw_minor_version = state->hs_fw.fw_rev_minor;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_fw_micro_version = state->hs_fw.fw_rev_subminor;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* CQ interrupt moderation maximums - each limited to 16 bits */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_cq_mod_count = 0xFFFF;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_cq_mod_usec = 0xFFFF;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hca_attr->hca_max_cq_handlers = state->hs_intrmsi_allocd;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine HCA capabilities:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * No default support for IBT_HCA_RD, IBT_HCA_RAW_MULTICAST,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * IBT_HCA_ATOMICS_GLOBAL, IBT_HCA_RESIZE_CHAN, IBT_HCA_INIT_TYPE,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * or IBT_HCA_SHUTDOWN_PORT
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * But IBT_HCA_AH_PORT_CHECK, IBT_HCA_SQD_RTS_PORT, IBT_HCA_SI_GUID,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * IBT_HCA_RNR_NAK, IBT_HCA_CURRENT_QP_STATE, IBT_HCA_PORT_UP,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * IBT_HCA_SRQ, IBT_HCA_RESIZE_SRQ and IBT_HCA_FMR are always
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * supported
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * All other features are conditionally supported, depending on the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * status return by the Hermon HCA in QUERY_DEV_LIM.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_devlim.ud_multi) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor caps |= IBT_HCA_UD_MULTICAST;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_devlim.atomic) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor caps |= IBT_HCA_ATOMICS_HCA;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_devlim.apm) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor caps |= IBT_HCA_AUTO_PATH_MIG;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_devlim.pkey_v) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor caps |= IBT_HCA_PKEY_CNTR;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_devlim.qkey_v) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor caps |= IBT_HCA_QKEY_CNTR;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_devlim.ipoib_cksm) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor caps |= IBT_HCA_CKSUM_FULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor caps2 |= IBT_HCA2_IP_CLASS;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_devlim.mod_wr_srq) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor caps |= IBT_HCA_RESIZE_SRQ;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_devlim.lif) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor caps |= IBT_HCA_LOCAL_INVAL_FENCE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_devlim.reserved_lkey) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor caps2 |= IBT_HCA2_RES_LKEY;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_reserved_lkey = state->hs_devlim.rsv_lkey;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_devlim.local_inv && state->hs_devlim.remote_inv &&
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor state->hs_devlim.fast_reg_wr) { /* fw needs to be >= 2.7.000 */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if ((state->hs_fw.fw_rev_major > 2) ||
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor ((state->hs_fw.fw_rev_major == 2) &&
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor (state->hs_fw.fw_rev_minor >= 7)))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor caps2 |= IBT_HCA2_MEM_MGT_EXT;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (state->hs_devlim.log_max_rss_tbl_sz) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hca_attr->hca_rss_max_log2_table =
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor state->hs_devlim.log_max_rss_tbl_sz;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (state->hs_devlim.rss_xor)
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor caps2 |= IBT_HCA2_RSS_XOR_ALG;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (state->hs_devlim.rss_toep)
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor caps2 |= IBT_HCA2_RSS_TPL_ALG;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_devlim.mps) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor caps |= IBT_HCA_ZERO_BASED_VA;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_devlim.zb) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor caps |= IBT_HCA_MULT_PAGE_SZ_MR;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor caps |= (IBT_HCA_AH_PORT_CHECK | IBT_HCA_SQD_SQD_PORT |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBT_HCA_SI_GUID | IBT_HCA_RNR_NAK | IBT_HCA_CURRENT_QP_STATE |
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBT_HCA_PORT_UP | IBT_HCA_RC_SRQ | IBT_HCA_UD_SRQ | IBT_HCA_FMR);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor caps2 |= IBT_HCA2_DMA_MR;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_devlim.log_max_gso_sz) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_lso_size =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (1 << state->hs_devlim.log_max_gso_sz);
9c865d645a5c60028aed172eea31ca36d81a2ff1Rajkumar Sivaprakasam /* 64 = ctrl & datagram seg, 4 = LSO seg, 16 = 1 SGL */
9c865d645a5c60028aed172eea31ca36d81a2ff1Rajkumar Sivaprakasam hca_attr->hca_max_lso_hdr_size =
9c865d645a5c60028aed172eea31ca36d81a2ff1Rajkumar Sivaprakasam state->hs_devlim.max_desc_sz_sq - (64 + 4 + 16);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor caps |= IBT_HCA_WQE_SIZE_INFO;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor max_send_wqe_bytes = state->hs_devlim.max_desc_sz_sq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor max_recv_wqe_bytes = state->hs_devlim.max_desc_sz_rq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_ud_send_sgl_sz = (max_send_wqe_bytes / 16) - 4;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_conn_send_sgl_sz = (max_send_wqe_bytes / 16) - 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_conn_rdma_sgl_overhead = 1;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hca_attr->hca_conn_rdma_write_sgl_sz = (max_send_wqe_bytes / 16) - 2;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hca_attr->hca_conn_rdma_read_sgl_sz = (512 / 16) - 2; /* see PRM */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_recv_sgl_sz = max_recv_wqe_bytes / 16;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* We choose not to support "inline" unless it improves performance */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_inline_size = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_ud_send_inline_sz = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_conn_send_inline_sz = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_conn_rdmaw_inline_overhead = 4;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
f35eb4e637f5e925af3bb7993f3bb87c5a69a696Bill Taylor#if defined(_ELF64)
f35eb4e637f5e925af3bb7993f3bb87c5a69a696Bill Taylor /* 32-bit kernels are too small for Fibre Channel over IB */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (state->hs_devlim.fcoib && (caps2 & IBT_HCA2_MEM_MGT_EXT)) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor caps2 |= IBT_HCA2_FC;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hca_attr->hca_rfci_max_log2_qp = 7; /* 128 per port */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hca_attr->hca_fexch_max_log2_qp = 16; /* 64K per port */
f35eb4e637f5e925af3bb7993f3bb87c5a69a696Bill Taylor hca_attr->hca_fexch_max_log2_mem = 20; /* 1MB per MPT */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
f35eb4e637f5e925af3bb7993f3bb87c5a69a696Bill Taylor#endif
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_flags = caps;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_flags2 = caps2;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Set hca_attr's IDs
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_vendor_id = state->hs_vendor_id;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_device_id = state->hs_device_id;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_version_id = state->hs_revision_id;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine number of available QPs and max QP size. Number of
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * available QPs is determined by subtracting the number of
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "reserved QPs" (i.e. reserved for firmware use) from the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * total number configured.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = ((uint64_t)1 << state->hs_cfg_profile->cp_log_num_qp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_qp = val - ((uint64_t)1 <<
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_devlim.log_rsvd_qp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor maxval = ((uint64_t)1 << state->hs_devlim.log_max_qp_sz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = ((uint64_t)1 << state->hs_cfg_profile->cp_log_max_qp_sz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (val > maxval) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "soft_state_init_maxqpsz_toobig_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* we need to reduce this by the max space needed for headroom */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_qp_sz = (uint_t)val - (HERMON_QP_OH_SIZE >>
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_QP_WQE_LOG_MINIMUM) - 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine max scatter-gather size in WQEs. The HCA has split
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the max sgl into rec'v Q and send Q values. Use the least.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * This is mainly useful for legacy clients. Smart clients
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * such as IPoIB will use the IBT_HCA_WQE_SIZE_INFO sgl info.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_devlim.max_sg_rq <= state->hs_devlim.max_sg_sq) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor maxval = state->hs_devlim.max_sg_rq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor maxval = state->hs_devlim.max_sg_sq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = state->hs_cfg_profile->cp_wqe_max_sgl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (val > maxval) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "soft_state_init_toomanysgl_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* If the rounded value for max SGL is too large, cap it */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_cfg_profile->cp_wqe_real_max_sgl > maxval) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_cfg_profile->cp_wqe_real_max_sgl = (uint32_t)maxval;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = maxval;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = state->hs_cfg_profile->cp_wqe_real_max_sgl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_sgl = (uint_t)val;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_rd_sgl = 0; /* zero because RD is unsupported */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine number of available CQs and max CQ size. Number of
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * available CQs is determined by subtracting the number of
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "reserved CQs" (i.e. reserved for firmware use) from the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * total number configured.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = ((uint64_t)1 << state->hs_cfg_profile->cp_log_num_cq);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_cq = val - ((uint64_t)1 <<
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_devlim.log_rsvd_cq);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor maxval = ((uint64_t)1 << state->hs_devlim.log_max_cq_sz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = ((uint64_t)1 << state->hs_cfg_profile->cp_log_max_cq_sz) - 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (val > maxval) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "soft_state_init_maxcqsz_toobig_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_cq_sz = (uint_t)val;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine number of available SRQs and max SRQ size. Number of
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * available SRQs is determined by subtracting the number of
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "reserved SRQs" (i.e. reserved for firmware use) from the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * total number configured.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = ((uint64_t)1 << state->hs_cfg_profile->cp_log_num_srq);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_srqs = val - ((uint64_t)1 <<
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_devlim.log_rsvd_srq);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor maxval = ((uint64_t)1 << state->hs_devlim.log_max_srq_sz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = ((uint64_t)1 << state->hs_cfg_profile->cp_log_max_srq_sz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (val > maxval) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "soft_state_init_maxsrqsz_toobig_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_srqs_sz = (uint_t)val;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = hca_attr->hca_recv_sgl_sz - 1; /* SRQ has a list link */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor maxval = state->hs_devlim.max_sg_rq - 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (val > maxval) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "soft_state_init_toomanysrqsgl_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_srq_sgl = (uint_t)val;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine supported HCA page sizes
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * XXX
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * For now we simply return the system pagesize as the only supported
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * pagesize
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_page_sz = ((PAGESIZE == (1 << 13)) ? IBT_PAGE_8K :
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBT_PAGE_4K);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine number of available MemReg, MemWin, and their max size.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Number of available MRs and MWs is determined by subtracting
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the number of "reserved MPTs" (i.e. reserved for firmware use)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * from the total number configured for each.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = ((uint64_t)1 << state->hs_cfg_profile->cp_log_num_dmpt);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_memr = val - ((uint64_t)1 <<
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_devlim.log_rsvd_dmpt);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_mem_win = state->hs_devlim.mem_win ? (val -
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ((uint64_t)1 << state->hs_devlim.log_rsvd_dmpt)) : 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor maxval = state->hs_devlim.log_max_mrw_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = state->hs_cfg_profile->cp_log_max_mrw_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (val > maxval) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "soft_state_init_maxmrwsz_toobig_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_memr_len = ((uint64_t)1 << val);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Determine RDMA/Atomic properties */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = ((uint64_t)1 << state->hs_cfg_profile->cp_log_num_rdb);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_rsc = (uint_t)val;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = state->hs_cfg_profile->cp_hca_max_rdma_in_qp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_rdma_in_qp = (uint8_t)val;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = state->hs_cfg_profile->cp_hca_max_rdma_out_qp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_rdma_out_qp = (uint8_t)val;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_rdma_in_ee = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_rdma_out_ee = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine maximum number of raw IPv6 and Ether QPs. Set to 0
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * because neither type of raw QP is supported
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_ipv6_qp = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_ether_qp = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Determine max number of MCGs and max QP-per-MCG */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = ((uint64_t)1 << state->hs_cfg_profile->cp_log_num_qp);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_mcg_qps = (uint_t)val;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = ((uint64_t)1 << state->hs_cfg_profile->cp_log_num_mcg);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_mcg = (uint_t)val;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = state->hs_cfg_profile->cp_num_qp_per_mcg;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_qp_per_mcg = (uint_t)val;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Determine max number partitions (i.e. PKeys) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor maxval = ((uint64_t)state->hs_cfg_profile->cp_num_ports <<
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_queryport.log_max_pkey);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = ((uint64_t)state->hs_cfg_profile->cp_num_ports <<
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_cfg_profile->cp_log_max_pkeytbl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (val > maxval) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "soft_state_init_toomanypkey_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_partitions = (uint16_t)val;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Determine number of ports */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor maxval = state->hs_devlim.num_ports;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = state->hs_cfg_profile->cp_num_ports;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((val > maxval) || (val == 0)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "soft_state_init_toomanyports_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_nports = (uint8_t)val;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Copy NodeGUID and SystemImageGUID from softstate */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_node_guid = state->hs_nodeguid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_si_guid = state->hs_sysimgguid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine local ACK delay. Use the value suggested by the Hermon
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hardware (from the QUERY_DEV_CAP command)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_local_ack_delay = state->hs_devlim.ca_ack_delay;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Determine max SGID table and PKey table sizes */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = ((uint64_t)1 << state->hs_cfg_profile->cp_log_max_gidtbl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_port_sgid_tbl_sz = (uint_t)val;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = ((uint64_t)1 << state->hs_cfg_profile->cp_log_max_pkeytbl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_port_pkey_tbl_sz = (uint16_t)val;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Determine max number of PDs */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor maxval = ((uint64_t)1 << state->hs_devlim.log_max_pd);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = ((uint64_t)1 << state->hs_cfg_profile->cp_log_num_pd);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (val > maxval) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "soft_state_init_toomanypd_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_pd = (uint_t)val;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Determine max number of Address Handles (NOT IN ARBEL or HERMON) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_ah = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* No RDDs or EECs (since Reliable Datagram is not supported) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_rdd = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hca_attr->hca_max_eec = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize lock for reserved UAR page access */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_init(&state->hs_uar_lock, NULL, MUTEX_DRIVER,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor DDI_INTR_PRI(state->hs_intrmsi_pri));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize the flash fields */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw_flashstarted = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_init(&state->hs_fw_flashlock, NULL, MUTEX_DRIVER,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor DDI_INTR_PRI(state->hs_intrmsi_pri));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize the lock for the info ioctl */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_init(&state->hs_info_lock, NULL, MUTEX_DRIVER,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor DDI_INTR_PRI(state->hs_intrmsi_pri));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize the AVL tree for QP number support */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_qpn_avl_init(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor /* Initialize the cq_sched info structure */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor status = hermon_cq_sched_init(state);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (status != DDI_SUCCESS) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_qpn_avl_fini(state);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor mutex_destroy(&state->hs_info_lock);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor mutex_destroy(&state->hs_fw_flashlock);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor mutex_destroy(&state->hs_uar_lock);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor "soft_state_init_cqsched_init_fail");
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor return (DDI_FAILURE);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor /* Initialize the fcoib info structure */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor status = hermon_fcoib_init(state);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (status != DDI_SUCCESS) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_cq_sched_fini(state);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_qpn_avl_fini(state);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor mutex_destroy(&state->hs_info_lock);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor mutex_destroy(&state->hs_fw_flashlock);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor mutex_destroy(&state->hs_uar_lock);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor "soft_state_init_fcoibinit_fail");
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor return (DDI_FAILURE);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize the kstat info structure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_kstat_init(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_fcoib_fini(state);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_cq_sched_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_qpn_avl_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_destroy(&state->hs_info_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_destroy(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_destroy(&state->hs_uar_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(hca_attr, sizeof (ibt_hca_attr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "soft_state_init_kstatinit_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_soft_state_fini()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Called only from detach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_soft_state_fini(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Teardown the kstat info */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_kstat_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor /* Teardown the fcoib info */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_fcoib_fini(state);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor /* Teardown the cq_sched info */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_cq_sched_fini(state);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Teardown the AVL tree for QP number support */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_qpn_avl_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free up info ioctl mutex */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_destroy(&state->hs_info_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free up flash mutex */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_destroy(&state->hs_fw_flashlock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free up the UAR page access mutex */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_destroy(&state->hs_uar_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free up the hca_attr struct */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(state->hs_ibtfinfo.hca_attr, sizeof (ibt_hca_attr_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_icm_config_setup()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_icm_config_setup(hermon_state_t *state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_initqueryhca_t *inithca)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_querydevlim_t *devlim;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_cfg_profile_t *cfg;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_icm_table_t *icm_p[HERMON_NUM_ICM_RESOURCES];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_icm_table_t *icm;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_icm_table_t *tmp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t icm_addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t icm_size;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status, i, j;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Bring in local devlims, cfg_profile and hs_icm table list */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor devlim = &state->hs_devlim;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cfg = state->hs_cfg_profile;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm = state->hs_icm;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Assign each ICM table's entry size from data in the devlims,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * except for RDB and MCG sizes, which are not returned in devlims
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * but do have a fixed size, and the UAR context entry size, which
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * we determine. For this, we use the "cp_num_pgs_per_uce" value
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * from our hs_cfg_profile.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_CMPT].object_size = devlim->cmpt_entry_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_CMPT_QPC].object_size = devlim->cmpt_entry_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_CMPT_SRQC].object_size = devlim->cmpt_entry_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_CMPT_CQC].object_size = devlim->cmpt_entry_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_CMPT_EQC].object_size = devlim->cmpt_entry_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_MTT].object_size = devlim->mtt_entry_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_DMPT].object_size = devlim->dmpt_entry_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_QPC].object_size = devlim->qpc_entry_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_CQC].object_size = devlim->cqc_entry_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_SRQC].object_size = devlim->srq_entry_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_EQC].object_size = devlim->eqc_entry_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_RDB].object_size = devlim->rdmardc_entry_sz *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cfg->cp_hca_max_rdma_in_qp;
9fa01faf81019677b9c27c7bdf6a310284d4ccb1agiri icm[HERMON_MCG].object_size = HERMON_MCGMEM_SZ(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_ALTC].object_size = devlim->altc_entry_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_AUXC].object_size = devlim->aux_entry_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Assign each ICM table's log2 number of entries */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_CMPT].log_num_entries = cfg->cp_log_num_cmpt;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_CMPT_QPC].log_num_entries = cfg->cp_log_num_qp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_CMPT_SRQC].log_num_entries = cfg->cp_log_num_srq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_CMPT_CQC].log_num_entries = cfg->cp_log_num_cq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_CMPT_EQC].log_num_entries = HERMON_NUM_EQ_SHIFT;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_MTT].log_num_entries = cfg->cp_log_num_mtt;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_DMPT].log_num_entries = cfg->cp_log_num_dmpt;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_QPC].log_num_entries = cfg->cp_log_num_qp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_SRQC].log_num_entries = cfg->cp_log_num_srq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_CQC].log_num_entries = cfg->cp_log_num_cq;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_EQC].log_num_entries = HERMON_NUM_EQ_SHIFT;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_RDB].log_num_entries = cfg->cp_log_num_qp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_MCG].log_num_entries = cfg->cp_log_num_mcg;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_ALTC].log_num_entries = cfg->cp_log_num_qp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[HERMON_AUXC].log_num_entries = cfg->cp_log_num_qp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize the ICM tables */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_icm_tables_init(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * ICM tables must be aligned on their size in the ICM address
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * space. So, here we order the tables from largest total table
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * size to the smallest. All tables are a power of 2 in size, so
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * this will ensure that all tables are aligned on their own size
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * without wasting space in the ICM.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * In order to easily set the ICM addresses without needing to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * worry about the ordering of our table indices as relates to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the hermon_rsrc_type_t enum, we will use a list of pointers
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * representing the tables for the sort, then assign ICM addresses
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * below using it.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < HERMON_NUM_ICM_RESOURCES; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm_p[i] = &icm[i];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = HERMON_NUM_ICM_RESOURCES; i > 0; i--) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (i) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CMPT_QPC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CMPT_SRQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CMPT_CQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CMPT_EQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor continue;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (j = 1; j < i; j++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (icm_p[j]->table_size > icm_p[j - 1]->table_size) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor tmp = icm_p[j];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm_p[j] = icm_p[j - 1];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm_p[j - 1] = tmp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize the ICM address and ICM size */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm_addr = icm_size = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Set the ICM base address of each table, using our sorted
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * list of pointers from above.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < HERMON_NUM_ICM_RESOURCES; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor j = icm_p[i]->icm_type;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (j) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CMPT_QPC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CMPT_SRQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CMPT_CQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CMPT_EQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor continue;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (icm[j].table_size) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Set the ICM base address in the table, save the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * ICM offset in the rsrc pool and increment the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * total ICM allocation.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[j].icm_baseaddr = icm_addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_verbose) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBTF_DPRINTF_L2("ICMADDR", "rsrc %x @ %p"
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor " size %llx", j, icm[j].icm_baseaddr,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[j].table_size);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm_size += icm[j].table_size;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Verify that we don't exceed maximum ICM size */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (icm_size > devlim->max_icm_size) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* free the ICM table memory resources */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_icm_tables_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_WARN, "ICM configuration exceeds maximum "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "configuration: max (0x%lx) requested (0x%lx)\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (ulong_t)devlim->max_icm_size, (ulong_t)icm_size);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "icm_config_toobig_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* assign address to the 4 pieces of the CMPT */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (j == HERMON_CMPT) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t cmpt_size = icm[j].table_size >> 2;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#define init_cmpt_icm_baseaddr(rsrc, indx) \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[rsrc].icm_baseaddr = icm_addr + (indx * cmpt_size);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor init_cmpt_icm_baseaddr(HERMON_CMPT_QPC, 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor init_cmpt_icm_baseaddr(HERMON_CMPT_SRQC, 1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor init_cmpt_icm_baseaddr(HERMON_CMPT_CQC, 2);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor init_cmpt_icm_baseaddr(HERMON_CMPT_EQC, 3);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Increment the ICM address for the next table */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm_addr += icm[j].table_size;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Populate the structure for the INIT_HCA command */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_inithca_set(state, inithca);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Prior to invoking INIT_HCA, we must have ICM memory in place
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * for the reserved objects in each table. We will allocate and map
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * this initial ICM memory here. Note that given the assignment
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * of span_size above, tables that are smaller or equal in total
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * size to the default span_size will be mapped in full.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_icm_dma_init(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* free the ICM table memory resources */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_icm_tables_fini(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WARNING(state, "Failed to allocate initial ICM");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_ATTACH_MSG(state->hs_attach_buf,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "icm_config_dma_init_fail");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_inithca_set()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_inithca_set(hermon_state_t *state, hermon_hw_initqueryhca_t *inithca)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_cfg_profile_t *cfg;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_icm_table_t *icm;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Populate the INIT_HCA structure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm = state->hs_icm;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cfg = state->hs_cfg_profile;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* set version */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->version = 0x02; /* PRM 0.36 */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* set cacheline - log2 in 16-byte chunks */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->log2_cacheline = 0x2; /* optimized for 64 byte cache */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* we need to update the inithca info with thie UAR info too */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->uar.log_max_uars = highbit(cfg->cp_log_num_uar);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->uar.uar_pg_sz = PAGESHIFT - HERMON_PAGESHIFT;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set endianess */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef _LITTLE_ENDIAN
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->big_endian = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#else
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->big_endian = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Port Checking is on by default */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->udav_port_chk = HERMON_UDAV_PORTCHK_ENABLED;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Enable IPoIB checksum */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_devlim.ipoib_cksm)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->chsum_en = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set each ICM table's attributes */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < HERMON_NUM_ICM_RESOURCES; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (icm[i].icm_type) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CMPT:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->tpt.cmpt_baseaddr = icm[i].icm_baseaddr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_MTT:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->tpt.mtt_baseaddr = icm[i].icm_baseaddr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_DMPT:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->tpt.dmpt_baseaddr = icm[i].icm_baseaddr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->tpt.log_dmpt_sz = icm[i].log_num_entries;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->tpt.pgfault_rnr_to = 0; /* just in case */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_QPC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->context.log_num_qp = icm[i].log_num_entries;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->context.qpc_baseaddr_h =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].icm_baseaddr >> 32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->context.qpc_baseaddr_l =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (icm[i].icm_baseaddr & 0xFFFFFFFF) >> 5;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->context.log_num_cq = icm[i].log_num_entries;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->context.cqc_baseaddr_h =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].icm_baseaddr >> 32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->context.cqc_baseaddr_l =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (icm[i].icm_baseaddr & 0xFFFFFFFF) >> 5;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_SRQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->context.log_num_srq = icm[i].log_num_entries;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->context.srqc_baseaddr_h =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].icm_baseaddr >> 32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->context.srqc_baseaddr_l =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (icm[i].icm_baseaddr & 0xFFFFFFFF) >> 5;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_EQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->context.log_num_eq = icm[i].log_num_entries;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->context.eqc_baseaddr_h =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].icm_baseaddr >> 32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->context.eqc_baseaddr_l =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (icm[i].icm_baseaddr & 0xFFFFFFFF) >> 5;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_RDB:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->context.rdmardc_baseaddr_h =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].icm_baseaddr >> 32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->context.rdmardc_baseaddr_l =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (icm[i].icm_baseaddr & 0xFFFFFFFF) >> 5;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->context.log_num_rdmardc =
80ba55855aa63819ae7c0d4f91482199f613ce6bBill Taylor cfg->cp_log_num_rdb - cfg->cp_log_num_qp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_MCG:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->multi.mc_baseaddr = icm[i].icm_baseaddr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->multi.log_mc_tbl_sz = icm[i].log_num_entries;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->multi.log_mc_tbl_ent =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor highbit(HERMON_MCGMEM_SZ(state)) - 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->multi.log_mc_tbl_hash_sz =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cfg->cp_log_num_mcg_hash;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->multi.mc_hash_fn = HERMON_MCG_DEFAULT_HASH_FN;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_ALTC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->context.altc_baseaddr = icm[i].icm_baseaddr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_AUXC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor inithca->context.auxc_baseaddr = icm[i].icm_baseaddr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_icm_tables_init()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Dynamic ICM breaks the various ICM tables into "span_size" chunks
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to enable allocation of backing memory on demand. Arbel used a
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * fixed size ARBEL_ICM_SPAN_SIZE (initially was 512KB) as the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * span_size for all ICM chunks. Hermon has other considerations,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * so the span_size used differs from Arbel.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * The basic considerations for why Hermon differs are:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 1) ICM memory is in units of HERMON pages.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 2) The AUXC table is approximately 1 byte per QP.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 3) ICM memory for AUXC, ALTC, and RDB is allocated when
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the ICM memory for the corresponding QPC is allocated.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * 4) ICM memory for the CMPT corresponding to the various primary
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * resources (QPC, SRQC, CQC, and EQC) is allocated when the ICM
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * memory for the primary resource is allocated.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * One HERMON page (4KB) would typically map 4K QPs worth of AUXC.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * So, the minimum chunk for the various QPC related ICM memory should
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * all be allocated to support the 4K QPs. Currently, this means the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * amount of memory for the various QP chunks is:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * QPC 256*4K bytes
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * RDB 128*4K bytes
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * CMPT 64*4K bytes
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * ALTC 64*4K bytes
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * AUXC 1*4K bytes
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * The span_size chosen for the QP resource is 4KB of AUXC entries,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * or 1 HERMON_PAGESIZE worth, which is the minimum ICM mapping size.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Other ICM resources can have their span_size be more arbitrary.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * This is 4K (HERMON_ICM_SPAN), except for MTTs because they are tiny.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* macro to make the code below cleaner */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#define init_dependent(rsrc, dep) \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[dep].span = icm[rsrc].span; \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[dep].num_spans = icm[rsrc].num_spans; \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[dep].split_shift = icm[rsrc].split_shift; \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[dep].span_mask = icm[rsrc].span_mask; \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[dep].span_shift = icm[rsrc].span_shift; \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[dep].rsrc_mask = icm[rsrc].rsrc_mask; \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_verbose) { \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBTF_DPRINTF_L2("hermon", "tables_init: " \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "rsrc (0x%x) size (0x%lx) span (0x%x) " \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "num_spans (0x%x)", dep, icm[dep].table_size, \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[dep].span, icm[dep].num_spans); \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBTF_DPRINTF_L2("hermon", "tables_init: " \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "span_shift (0x%x) split_shift (0x%x)", \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[dep].span_shift, icm[dep].split_shift); \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBTF_DPRINTF_L2("hermon", "tables_init: " \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "span_mask (0x%x) rsrc_mask (0x%x)", \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[dep].span_mask, icm[dep].rsrc_mask); \
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_icm_tables_init(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_icm_table_t *icm;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i, k;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t per_split;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm = state->hs_icm;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < HERMON_NUM_ICM_RESOURCES; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].icm_type = i;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].num_entries = 1 << icm[i].log_num_entries;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].log_object_size = highbit(icm[i].object_size) - 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].table_size = icm[i].num_entries <<
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].log_object_size;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* deal with "dependent" resource types */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (i) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_AUXC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef HERMON_FW_WORKAROUND
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].table_size = 0x80000000ull;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* FALLTHROUGH */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CMPT_QPC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_RDB:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_ALTC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor init_dependent(HERMON_QPC, i);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor continue;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CMPT_SRQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor init_dependent(HERMON_SRQC, i);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor continue;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CMPT_CQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor init_dependent(HERMON_CQC, i);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor continue;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CMPT_EQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor init_dependent(HERMON_EQC, i);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor continue;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].span = HERMON_ICM_SPAN; /* default #rsrc's in 1 span */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (i == HERMON_MTT) /* Alloc enough MTTs to map 256MB */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].span = HERMON_ICM_SPAN * 16;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].num_spans = icm[i].num_entries / icm[i].span;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (icm[i].num_spans == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].span = icm[i].num_entries;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor per_split = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].num_spans = icm[i].num_entries / icm[i].span;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor per_split = icm[i].num_spans / HERMON_ICM_SPLIT;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (per_split == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor per_split = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_verbose)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBTF_DPRINTF_L2("ICM", "rsrc %x span %x num_spans %x",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor i, icm[i].span, icm[i].num_spans);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Ensure a minimum table size of an ICM page, and a
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * maximum span size of the ICM table size. This ensures
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * that we don't have less than an ICM page to map, which is
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * impossible, and that we will map an entire table at
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * once if it's total size is less than the span size.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].table_size = max(icm[i].table_size, HERMON_PAGESIZE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].span_shift = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (k = icm[i].span; k != 1; k >>= 1)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].span_shift++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].split_shift = icm[i].span_shift;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (k = per_split; k != 1; k >>= 1)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].split_shift++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].span_mask = (1 << icm[i].split_shift) -
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (1 << icm[i].span_shift);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].rsrc_mask = (1 << icm[i].span_shift) - 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize the table lock */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_init(&icm[i].icm_table_lock, NULL, MUTEX_DRIVER,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor DDI_INTR_PRI(state->hs_intrmsi_pri));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cv_init(&icm[i].icm_table_cv, NULL, CV_DRIVER, NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_verbose) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBTF_DPRINTF_L2("hermon", "tables_init: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "rsrc (0x%x) size (0x%lx)", i, icm[i].table_size);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBTF_DPRINTF_L2("hermon", "tables_init: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "span (0x%x) num_spans (0x%x)",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].span, icm[i].num_spans);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBTF_DPRINTF_L2("hermon", "tables_init: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "span_shift (0x%x) split_shift (0x%x)",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].span_shift, icm[i].split_shift);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBTF_DPRINTF_L2("hermon", "tables_init: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "span_mask (0x%x) rsrc_mask (0x%x)",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm[i].span_mask, icm[i].rsrc_mask);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_icm_tables_fini()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Clean up all icm_tables. Free the bitmap and dma_info arrays.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_icm_tables_fini(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_icm_table_t *icm;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int nspans;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i, j;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm = state->hs_icm;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < HERMON_NUM_ICM_RESOURCES; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&icm[i].icm_table_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nspans = icm[i].num_spans;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (j = 0; j < HERMON_ICM_SPLIT; j++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (icm[i].icm_dma[j])
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the ICM DMA slots */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(icm[i].icm_dma[j],
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nspans * sizeof (hermon_dma_info_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (icm[i].icm_bitmap[j])
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the table bitmap */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(icm[i].icm_bitmap[j],
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (nspans + 7) / 8);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Destroy the table lock */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cv_destroy(&icm[i].icm_table_cv);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&icm[i].icm_table_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_destroy(&icm[i].icm_table_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_icm_dma_init()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_icm_dma_init(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_icm_table_t *icm;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_type_t type;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * This routine will allocate initial ICM DMA resources for ICM
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * tables that have reserved ICM objects. This is the only routine
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * where we should have to allocate ICM outside of hermon_rsrc_alloc().
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * We need to allocate ICM here explicitly, rather than in
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_rsrc_alloc(), because we've not yet completed the resource
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * pool initialization. When the resource pools are initialized
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * (in hermon_rsrc_init_phase2(), see hermon_rsrc.c for more
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * information), resource preallocations will be invoked to match
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the ICM allocations seen here. We will then be able to use the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * normal allocation path. Note we don't need to set a refcnt on
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * these initial allocations because that will be done in the calls
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to hermon_rsrc_alloc() from hermon_hw_entries_init() for the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "prealloc" objects (see hermon_rsrc.c for more information).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (type = 0; type < HERMON_NUM_ICM_RESOURCES; type++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* ICM for these is allocated within hermon_icm_alloc() */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (type) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CMPT:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CMPT_QPC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CMPT_SRQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CMPT_CQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_CMPT_EQC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_AUXC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_ALTC:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_RDB:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor continue;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm = &state->hs_icm[type];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&icm->icm_table_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_icm_alloc(state, type, 0, 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&icm->icm_table_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor while (type--) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm = &state->hs_icm[type];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_enter(&icm->icm_table_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_icm_free(state, type, 0, 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_exit(&icm->icm_table_lock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_verbose) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor IBTF_DPRINTF_L2("hermon", "hermon_icm_dma_init: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "table (0x%x) index (0x%x) allocated", type, 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_icm_dma_fini()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * ICM has been completely unmapped. We just free the memory here.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_icm_dma_fini(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_icm_table_t *icm;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_dma_info_t *dma_info;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_type_t type;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int index1, index2;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (type = 0; type < HERMON_NUM_ICM_RESOURCES; type++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor icm = &state->hs_icm[type];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (index1 = 0; index1 < HERMON_ICM_SPLIT; index1++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_info = icm->icm_dma[index1];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (dma_info == NULL)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor continue;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (index2 = 0; index2 < icm->num_spans; index2++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (dma_info[index2].dma_hdl)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_dma_free(&dma_info[index2]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dma_info[index2].dma_hdl = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_hca_port_init()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_hca_port_init(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_hw_set_port_t *portinits, *initport;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_cfg_profile_t *cfgprof;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t num_ports;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i = 0, status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t maxval, val;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t sysimgguid, nodeguid, portguid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cfgprof = state->hs_cfg_profile;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Get number of HCA ports */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor num_ports = cfgprof->cp_num_ports;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Allocate space for Hermon set port struct(s) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor portinits = (hermon_hw_set_port_t *)kmem_zalloc(num_ports *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_set_port_t), KM_SLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Post commands to initialize each Hermon HCA port */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * In Hermon, the process is different than in previous HCAs.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Here, you have to:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * QUERY_PORT - to get basic information from the HCA
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * set the fields accordingly
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * SET_PORT - to change/set everything as desired
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * INIT_PORT - to bring the port up
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Needs to be done for each port in turn
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < num_ports; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(&state->hs_queryport, sizeof (hermon_hw_query_port_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_cmn_query_cmd_post(state, QUERY_PORT, 0,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (i + 1), &state->hs_queryport,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sizeof (hermon_hw_query_port_t), HERMON_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != HERMON_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Hermon: QUERY_PORT (port %02d) "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "command failed: %08x\n", i + 1, status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto init_ports_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor initport = &portinits[i];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_initport = &portinits[i];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(initport, sizeof (hermon_hw_query_port_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine whether we need to override the firmware's
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * default SystemImageGUID setting.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sysimgguid = cfgprof->cp_sysimgguid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (sysimgguid != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor initport->sig = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor initport->sys_img_guid = sysimgguid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine whether we need to override the firmware's
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * default NodeGUID setting.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor nodeguid = cfgprof->cp_nodeguid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (nodeguid != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor initport->ng = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor initport->node_guid = nodeguid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Determine whether we need to override the firmware's
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * default PortGUID setting.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor portguid = cfgprof->cp_portguid[i];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (portguid != 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor initport->g0 = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor initport->guid0 = portguid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Validate max MTU size */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor maxval = state->hs_queryport.ib_mtu;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = cfgprof->cp_max_mtu;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (val > maxval) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto init_ports_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
71be8d8f808a6f8b1a1bbb502fb01c7ccdb8512dBill Taylor /* Set mtu_cap to 4096 bytes */
71be8d8f808a6f8b1a1bbb502fb01c7ccdb8512dBill Taylor initport->mmc = 1; /* set the change bit */
71be8d8f808a6f8b1a1bbb502fb01c7ccdb8512dBill Taylor initport->mtu_cap = 5; /* for 4096 bytes */
71be8d8f808a6f8b1a1bbb502fb01c7ccdb8512dBill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Validate the max port width */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor maxval = state->hs_queryport.ib_port_wid;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = cfgprof->cp_max_port_width;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (val > maxval) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto init_ports_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Validate max VL cap size */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor maxval = state->hs_queryport.max_vl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = cfgprof->cp_max_vlcap;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (val > maxval) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto init_ports_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
71be8d8f808a6f8b1a1bbb502fb01c7ccdb8512dBill Taylor /* Since we're doing mtu_cap, cut vl_cap down */
71be8d8f808a6f8b1a1bbb502fb01c7ccdb8512dBill Taylor initport->mvc = 1; /* set this change bit */
71be8d8f808a6f8b1a1bbb502fb01c7ccdb8512dBill Taylor initport->vl_cap = 3; /* 3 means vl0-vl3, 4 total */
71be8d8f808a6f8b1a1bbb502fb01c7ccdb8512dBill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Validate max GID table size */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor maxval = ((uint64_t)1 << state->hs_queryport.log_max_gid);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = ((uint64_t)1 << cfgprof->cp_log_max_gidtbl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (val > maxval) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto init_ports_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor initport->max_gid = (uint16_t)val;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor initport->mg = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Validate max PKey table size */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor maxval = ((uint64_t)1 << state->hs_queryport.log_max_pkey);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = ((uint64_t)1 << cfgprof->cp_log_max_pkeytbl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (val > maxval) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto init_ports_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor initport->max_pkey = (uint16_t)val;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor initport->mp = 1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Post the SET_PORT cmd to Hermon firmware. This sets
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the parameters of the port.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_set_port_cmd_post(state, initport, i + 1,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != HERMON_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Hermon: SET_PORT (port %02d) command "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "failed: %08x\n", i + 1, status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto init_ports_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* issue another SET_PORT cmd - performance fix/workaround */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* XXX - need to discuss with Mellanox */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor bzero(initport, sizeof (hermon_hw_query_port_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor initport->cap_mask = 0x02500868;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_set_port_cmd_post(state, initport, i + 1,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != HERMON_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Hermon: SET_PORT (port %02d) command "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "failed: %08x\n", i + 1, status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto init_ports_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Finally, do the INIT_PORT for each port in turn
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * When this command completes, the corresponding Hermon port
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * will be physically "Up" and initialized.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < num_ports; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_init_port_cmd_post(state, i + 1,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != HERMON_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Hermon: INIT_PORT (port %02d) "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "comman failed: %08x\n", i + 1, status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto init_ports_fail;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free up the memory for Hermon port init struct(s), return success */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(portinits, num_ports * sizeof (hermon_hw_set_port_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorinit_ports_fail:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Free up the memory for Hermon port init struct(s), shutdown any
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * successfully initialized ports, and return failure
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(portinits, num_ports * sizeof (hermon_hw_set_port_t));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) hermon_hca_ports_shutdown(state, i);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_hca_ports_shutdown()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() and/or detach() path contexts
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_hca_ports_shutdown(hermon_state_t *state, uint_t num_init)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i, status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Post commands to shutdown all init'd Hermon HCA ports. Note: if
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * any of these commands fail for any reason, it would be entirely
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * unexpected and probably indicative a serious problem (HW or SW).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Although we do return void from this function, this type of failure
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * should not go unreported. That is why we have the warning message.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < num_init; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_close_port_cmd_post(state, i + 1,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_CMD_NOSLEEP_SPIN);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != HERMON_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_WARNING(state, "failed to shutdown HCA port");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (HERMON_CMD_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_internal_uarpg_init
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_internal_uarpg_init(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_dbr_info_t *info;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Allocate the UAR page for kernel use. This UAR page is
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the privileged UAR page through which all kernel generated
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * doorbells will be rung. There are a number of UAR pages
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * reserved by hardware at the front of the UAR BAR, indicated
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * by DEVCAP.num_rsvd_uar, which we have already allocated. So,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the kernel page, or UAR page index num_rsvd_uar, will be
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * allocated here for kernel use.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_rsrc_alloc(state, HERMON_UARPG, 1, HERMON_SLEEP,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_uarkpg_rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Setup pointer to kernel UAR page */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_uar = (hermon_hw_uar_t *)state->hs_uarkpg_rsrc->hr_addr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* need to set up DBr tracking as well */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_dbr_page_alloc(state, &info);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
dd9e16da4243358c2e9251a4ca5d50f56e0adc68agiri state->hs_kern_dbr = info;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_internal_uarpg_fini
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() and/or detach() path contexts
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_internal_uarpg_fini(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free up Hermon UAR page #1 (kernel driver doorbells) */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_free(state, &state->hs_uarkpg_rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_special_qp_contexts_reserve()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_special_qp_contexts_reserve(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_t *qp0_rsrc, *qp1_rsrc, *qp_resvd;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Initialize the lock used for special QP rsrc management */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_init(&state->hs_spec_qplock, NULL, MUTEX_DRIVER,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor DDI_INTR_PRI(state->hs_intrmsi_pri));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Reserve contexts for QP0. These QP contexts will be setup to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * act as aliases for the real QP0. Note: We are required to grab
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * two QPs (one per port) even if we are operating in single-port
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * mode.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_rsrc_alloc(state, HERMON_QPC, 2,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_SLEEP, &qp0_rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_destroy(&state->hs_spec_qplock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_spec_qp0 = qp0_rsrc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Reserve contexts for QP1. These QP contexts will be setup to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * act as aliases for the real QP1. Note: We are required to grab
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * two QPs (one per port) even if we are operating in single-port
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * mode.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_rsrc_alloc(state, HERMON_QPC, 2,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_SLEEP, &qp1_rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_free(state, &qp0_rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_destroy(&state->hs_spec_qplock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_spec_qp1 = qp1_rsrc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_rsrc_alloc(state, HERMON_QPC, 4,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_SLEEP, &qp_resvd);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_free(state, &qp1_rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_free(state, &qp0_rsrc);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_destroy(&state->hs_spec_qplock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_spec_qp_unused = qp_resvd;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_special_qp_contexts_unreserve()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() and/or detach() path contexts
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_special_qp_contexts_unreserve(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Unreserve contexts for spec_qp_unused */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_free(state, &state->hs_spec_qp_unused);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Unreserve contexts for QP1 */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_free(state, &state->hs_spec_qp1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Unreserve contexts for QP0 */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_rsrc_free(state, &state->hs_spec_qp0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Destroy the lock used for special QP rsrc management */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_destroy(&state->hs_spec_qplock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_sw_reset()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Currently called only from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_sw_reset(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t hdl = hermon_get_pcihdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t cmdhdl = hermon_get_cmdhdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t reset_delay;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status, i;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t sem;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t offset;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t data32; /* for devctl & linkctl */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int loopcnt;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* initialize the FMA retry loop */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_init(fm_loop_cnt, fm_status, fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_init(fm_loop_cnt2, fm_status2, fm_test2);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If the configured software reset delay is set to zero, then we
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * will not attempt a software reset of the Hermon device.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor reset_delay = state->hs_cfg_profile->cp_sw_reset_delay;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (reset_delay == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop starts. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_start(state, cmdhdl, pio_error, fm_loop_cnt, fm_status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_start(state, hdl, pio_error2, fm_loop_cnt2, fm_status2,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_test2);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Query the PCI capabilities of the HCA device */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* but don't process the VPD until after reset */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_pci_capability_list(state, hdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "failed to get pci capabilities list(0x%x)\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Read all PCI config info (reg0...reg63). Note: According to the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Hermon software reset application note, we should not read or
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * restore the values in reg22 and reg23.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * NOTE: For Hermon (and Arbel too) it says to restore the command
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * register LAST, and technically, you need to restore the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * PCIE Capability "device control" and "link control" (word-sized,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * at offsets 0x08 and 0x10 from the capbility ID respectively).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * We hold off restoring the command register - offset 0x4 - till last
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* 1st, wait for the semaphore assure accessibility - per PRM */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = -1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < NANOSEC/MICROSEC /* 1sec timeout */; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sem = ddi_get32(cmdhdl, state->hs_cmd_regs.sw_semaphore);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (sem == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor drv_usecwait(1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Check if timeout happens */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status == -1) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Remove this acc handle from Hermon, then log
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the error.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pci_config_teardown(state, &hdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_WARN, "hermon_sw_reset timeout: "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "failed to get the semaphore(0x%p)\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void *)state->hs_cmd_regs.sw_semaphore);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_IBA_ERR, HCA_ERR_NON_FATAL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < HERMON_SW_RESET_NUMREGS; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((i != HERMON_SW_RESET_REG22_RSVD) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (i != HERMON_SW_RESET_REG23_RSVD)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_cfg_data[i] = pci_config_get32(hdl, i << 2);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Perform the software reset (by writing 1 at offset 0xF0010)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_put32(cmdhdl, state->hs_cmd_regs.sw_reset, HERMON_SW_RESET_START);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * This delay is required so as not to cause a panic here. If the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * device is accessed too soon after reset it will not respond to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * config cycles, causing a Master Abort and panic.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor drv_usecwait(reset_delay);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Poll waiting for the device to finish resetting.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor loopcnt = 100; /* 100 times @ 100 usec - total delay 10 msec */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor while ((pci_config_get32(hdl, 0) & 0x0000FFFF) != PCI_VENID_MLX) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor drv_usecwait(HERMON_SW_RESET_POLL_DELAY);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (--loopcnt == 0)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break; /* just in case, break and go on */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (loopcnt == 0)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "!Never see VEND_ID - read == %X",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pci_config_get32(hdl, 0));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Restore the config info
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < HERMON_SW_RESET_NUMREGS; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (i == 1) continue; /* skip the status/ctrl reg */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((i != HERMON_SW_RESET_REG22_RSVD) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (i != HERMON_SW_RESET_REG23_RSVD)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pci_config_put32(hdl, i << 2, state->hs_cfg_data[i]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * PCI Express Capability - we saved during capability list, and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * we'll restore them here.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor offset = state->hs_pci_cap_offset;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data32 = state->hs_pci_cap_devctl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pci_config_put32(hdl, offset + HERMON_PCI_CAP_DEV_OFFS, data32);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data32 = state->hs_pci_cap_lnkctl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pci_config_put32(hdl, offset + HERMON_PCI_CAP_LNK_OFFS, data32);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pci_config_put32(hdl, 0x04, (state->hs_cfg_data[1] | 0x0006));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* the FMA retry loop ends. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_end(state, hdl, pio_error2, fm_loop_cnt2, fm_status2,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_test2);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pio_end(state, cmdhdl, pio_error, fm_loop_cnt, fm_status,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor fm_test);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorpio_error2:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* fall through */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorpio_error:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fm_ereport(state, HCA_SYS_ERR, HCA_ERR_NON_FATAL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_mcg_init()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_mcg_init(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t mcg_tmp_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Allocate space for the MCG temporary copy buffer. This is
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * used by the Attach/Detach Multicast Group code
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg_tmp_sz = HERMON_MCGMEM_SZ(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_mcgtmp = kmem_zalloc(mcg_tmp_sz, KM_SLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Initialize the multicast group mutex. This ensures atomic
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * access to add, modify, and remove entries in the multicast
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * group hash lists.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_init(&state->hs_mcglock, NULL, MUTEX_DRIVER,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor DDI_INTR_PRI(state->hs_intrmsi_pri));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_mcg_fini()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() and/or detach() path contexts
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_mcg_fini(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t mcg_tmp_sz;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free up the space used for the MCG temporary copy buffer */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mcg_tmp_sz = HERMON_MCGMEM_SZ(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor kmem_free(state->hs_mcgtmp, mcg_tmp_sz);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Destroy the multicast group mutex */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor mutex_destroy(&state->hs_mcglock);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_fw_version_check()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_fw_version_check(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t hermon_fw_ver_major;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t hermon_fw_ver_minor;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t hermon_fw_ver_subminor;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef FMA_TEST
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_test_num == -1) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Depending on which version of driver we have attached, and which
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * HCA we've attached, the firmware version checks will be different.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * We set up the comparison values for both Arbel and Sinai HCAs.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (state->hs_operational_mode) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case HERMON_HCA_MODE:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fw_ver_major = HERMON_FW_VER_MAJOR;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fw_ver_minor = HERMON_FW_VER_MINOR;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_fw_ver_subminor = HERMON_FW_VER_SUBMINOR;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If FW revision major number is less than acceptable,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * return failure, else if greater return success. If
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the major numbers are equal than check the minor number
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_fw.fw_rev_major < hermon_fw_ver_major) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else if (state->hs_fw.fw_rev_major > hermon_fw_ver_major) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Do the same check as above, except for minor revision numbers
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If the minor numbers are equal than check the subminor number
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_fw.fw_rev_minor < hermon_fw_ver_minor) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else if (state->hs_fw.fw_rev_minor > hermon_fw_ver_minor) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Once again we do the same check as above, except for the subminor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * revision number. If the subminor numbers are equal here, then
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * these are the same firmware version, return success
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_fw.fw_rev_subminor < hermon_fw_ver_subminor) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else if (state->hs_fw.fw_rev_subminor > hermon_fw_ver_subminor) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_device_info_report()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_device_info_report(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "?hermon%d: FW ver: %04d.%04d.%04d, "
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "HW rev: %02d\n", state->hs_instance, state->hs_fw.fw_rev_major,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fw.fw_rev_minor, state->hs_fw.fw_rev_subminor,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_revision_id);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "?hermon%d: %64s (0x%016" PRIx64 ")\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_instance, state->hs_nodedesc, state->hs_nodeguid);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_pci_capability_list()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_pci_capability_list(hermon_state_t *state, ddi_acc_handle_t hdl)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t offset, data;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t data32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_pci_cap_offset = 0; /* make sure it's cleared */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check for the "PCI Capabilities" bit in the "Status Register".
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Bit 4 in this register indicates the presence of a "PCI
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Capabilities" list.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * PCI-Express requires this bit to be set to 1.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data = pci_config_get16(hdl, 0x06);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((data & 0x10) == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Starting from offset 0x34 in PCI config space, find the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * head of "PCI capabilities" list, and walk the list. If
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * capabilities of a known type are encountered (e.g.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * "PCI-X Capability"), then call the appropriate handler
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * function.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor offset = pci_config_get8(hdl, 0x34);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor while (offset != 0x0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data = pci_config_get8(hdl, offset);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check for known capability types. Hermon has the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * following:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * o Power Mgmt (0x02)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * o VPD Capability (0x03)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * o PCI-E Capability (0x10)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * o MSIX Capability (0x11)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor switch (data) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case 0x01:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* power mgmt handling */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case 0x03:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Reading the PCIe VPD is inconsistent - that is, sometimes causes
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * problems on (mostly) X64, though we've also seen problems w/ Sparc
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and Tavor --- so, for now until it's root caused, don't try and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * read it
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef HERMON_VPD_WORKS
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pci_capability_vpd(state, hdl, offset);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#else
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor delay(100);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_pci_capability_vpd(state, hdl, offset);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case 0x10:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * PCI Express Capability - save offset & contents
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * for later in reset
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_pci_cap_offset = offset;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data32 = pci_config_get32(hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor offset + HERMON_PCI_CAP_DEV_OFFS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_pci_cap_devctl = data32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data32 = pci_config_get32(hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor offset + HERMON_PCI_CAP_LNK_OFFS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_pci_cap_lnkctl = data32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor case 0x11:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * MSIX support - nothing to do, taken care of in the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * MSI/MSIX interrupt frameworkd
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor default:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* just go on to the next */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Get offset of next entry in list */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor offset = pci_config_get8(hdl, offset + 1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_pci_read_vpd()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * utility routine for hermon_pci_capability_vpd()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_pci_read_vpd(ddi_acc_handle_t hdl, uint_t offset, uint32_t addr,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t *data)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int retry = 40; /* retry counter for EEPROM poll */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t val;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int vpd_addr = offset + 2;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int vpd_data = offset + 4;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * In order to read a 32-bit value from VPD, we are to write down
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the address (offset in the VPD itself) to the address register.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * To signal the read, we also clear bit 31. We then poll on bit 31
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * and when it is set, we can then read our 4 bytes from the data
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * register.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) pci_config_put32(hdl, offset, addr << 16);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor do {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor drv_usecwait(1000);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor val = pci_config_get16(hdl, vpd_addr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (val & 0x8000) { /* flag bit set */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *data = pci_config_get32(hdl, vpd_data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } while (--retry);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* read of flag failed write one message but count the failures */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (debug_vpd == 0)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor "!Failed to see flag bit after VPD addr write\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor debug_vpd++;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorvpd_read_fail:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_pci_capability_vpd()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_pci_capability_vpd(hermon_state_t *state, ddi_acc_handle_t hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t offset)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint8_t name_length;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint8_t pn_length;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i, err = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int vpd_str_id = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int vpd_ro_desc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int vpd_ro_pn_desc;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef _BIG_ENDIAN
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t data32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif /* _BIG_ENDIAN */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor union {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t vpd_int[HERMON_VPD_HDR_DWSIZE];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uchar_t vpd_char[HERMON_VPD_HDR_BSIZE];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } vpd;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Read in the Vital Product Data (VPD) to the extend needed
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * by the fwflash utility
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < HERMON_VPD_HDR_DWSIZE; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor err = hermon_pci_read_vpd(hdl, offset, i << 2, &vpd.vpd_int[i]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (err != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "!VPD read failed\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto out;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef _BIG_ENDIAN
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Need to swap bytes for big endian. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < HERMON_VPD_HDR_DWSIZE; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data32 = vpd.vpd_int[i];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor vpd.vpd_char[(i << 2) + 3] =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uchar_t)((data32 & 0xFF000000) >> 24);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor vpd.vpd_char[(i << 2) + 2] =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uchar_t)((data32 & 0x00FF0000) >> 16);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor vpd.vpd_char[(i << 2) + 1] =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uchar_t)((data32 & 0x0000FF00) >> 8);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor vpd.vpd_char[i << 2] = (uchar_t)(data32 & 0x000000FF);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif /* _BIG_ENDIAN */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Check for VPD String ID Tag */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (vpd.vpd_char[vpd_str_id] == 0x82) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* get the product name */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor name_length = (uint8_t)vpd.vpd_char[vpd_str_id + 1];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (name_length > sizeof (state->hs_hca_name)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "!VPD name too large (0x%x)\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor name_length);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto out;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) memcpy(state->hs_hca_name, &vpd.vpd_char[vpd_str_id + 3],
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor name_length);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_hca_name[name_length] = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* get the part number */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor vpd_ro_desc = name_length + 3; /* read-only tag location */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor vpd_ro_pn_desc = vpd_ro_desc + 3; /* P/N keyword location */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Verify read-only tag and Part Number keyword. */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (vpd.vpd_char[vpd_ro_desc] != 0x90 ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (vpd.vpd_char[vpd_ro_pn_desc] != 'P' &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor vpd.vpd_char[vpd_ro_pn_desc + 1] != 'N')) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "!VPD Part Number not found\n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto out;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pn_length = (uint8_t)vpd.vpd_char[vpd_ro_pn_desc + 2];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (pn_length > sizeof (state->hs_hca_pn)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "!VPD part number too large (0x%x)\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor name_length);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto out;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) memcpy(state->hs_hca_pn,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &vpd.vpd_char[vpd_ro_pn_desc + 3],
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pn_length);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_hca_pn[pn_length] = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_hca_pn_len = pn_length;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "!vpd %s\n", state->hs_hca_pn);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Wrong VPD String ID Tag */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_NOTE, "!VPD String ID Tag not found, tag: %02x\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor vpd.vpd_char[0]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor goto out;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorout:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_hca_pn_len = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_intr_or_msi_init()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() path context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_intr_or_msi_init(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Query for the list of supported interrupt event types */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_intr_get_supported_types(state->hs_dip,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_intr_types_avail);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If Hermon supports MSI-X in this system (and, if it
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hasn't been overridden by a configuration variable), then
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the default behavior is to use a single MSI-X. Otherwise,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * fallback to using legacy interrupts. Also, if MSI-X is chosen,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * but fails for whatever reasons, then next try MSI
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((state->hs_cfg_profile->cp_use_msi_if_avail != 0) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (state->hs_intr_types_avail & DDI_INTR_TYPE_MSIX)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_add_intrs(state, DDI_INTR_TYPE_MSIX);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status == DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_intr_type_chosen = DDI_INTR_TYPE_MSIX;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If Hermon supports MSI in this system (and, if it
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hasn't been overridden by a configuration variable), then
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the default behavior is to use a single MSIX. Otherwise,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * fallback to using legacy interrupts. Also, if MSI is chosen,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * but fails for whatever reasons, then fallback to using legacy
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * interrupts.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((state->hs_cfg_profile->cp_use_msi_if_avail != 0) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (state->hs_intr_types_avail & DDI_INTR_TYPE_MSI)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_add_intrs(state, DDI_INTR_TYPE_MSI);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status == DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_intr_type_chosen = DDI_INTR_TYPE_MSI;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * MSI interrupt allocation failed, or was not available. Fallback to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * legacy interrupt support.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_intr_types_avail & DDI_INTR_TYPE_FIXED) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = hermon_add_intrs(state, DDI_INTR_TYPE_FIXED);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status == DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_intr_type_chosen = DDI_INTR_TYPE_FIXED;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * None of MSI, MSI-X, nor legacy interrupts were successful.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Return failure.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor/* ARGSUSED */
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylorstatic int
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylorhermon_intr_cb_handler(dev_info_t *dip, ddi_cb_action_t action, void *cbarg,
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor void *arg1, void *arg2)
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor{
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_state_t *state = (hermon_state_t *)arg1;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor IBTF_DPRINTF_L2("hermon", "interrupt callback: instance %d, "
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor "action %d, cbarg %d\n", state->hs_instance, action,
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor (uint32_t)(uintptr_t)cbarg);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor return (DDI_SUCCESS);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor}
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_add_intrs()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() patch context
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_add_intrs(hermon_state_t *state, int intr_type)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (state->hs_intr_cb_hdl == NULL) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor status = ddi_cb_register(state->hs_dip, DDI_CB_FLAG_INTR,
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_intr_cb_handler, state, NULL,
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor &state->hs_intr_cb_hdl);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (status != DDI_SUCCESS) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor cmn_err(CE_CONT, "ddi_cb_register failed: 0x%x\n",
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor status);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor state->hs_intr_cb_hdl = NULL;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor return (DDI_FAILURE);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Get number of interrupts/MSI supported */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_intr_get_nintrs(state->hs_dip, intr_type,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_intrmsi_count);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor (void) ddi_cb_unregister(state->hs_intr_cb_hdl);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor state->hs_intr_cb_hdl = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Get number of available interrupts/MSI */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_intr_get_navail(state->hs_dip, intr_type,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_intrmsi_avail);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor (void) ddi_cb_unregister(state->hs_intr_cb_hdl);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor state->hs_intr_cb_hdl = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Ensure that we have at least one (1) usable MSI or interrupt */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((state->hs_intrmsi_avail < 1) || (state->hs_intrmsi_count < 1)) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor (void) ddi_cb_unregister(state->hs_intr_cb_hdl);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor state->hs_intr_cb_hdl = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor /*
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * Allocate the #interrupt/MSI handles.
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * The number we request is the minimum of these three values:
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * HERMON_MSIX_MAX driver maximum (array size)
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * hermon_msix_max /etc/system override to...
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * HERMON_MSIX_MAX
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor * state->hs_intrmsi_avail Maximum the ddi provides.
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_intr_alloc(state->hs_dip, &state->hs_intrmsi_hdl[0],
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor intr_type, 0, min(min(HERMON_MSIX_MAX, state->hs_intrmsi_avail),
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor hermon_msix_max), &state->hs_intrmsi_allocd, DDI_INTR_ALLOC_NORMAL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor (void) ddi_cb_unregister(state->hs_intr_cb_hdl);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor state->hs_intr_cb_hdl = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Ensure that we have allocated at least one (1) MSI or interrupt */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_intrmsi_allocd < 1) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor (void) ddi_cb_unregister(state->hs_intr_cb_hdl);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor state->hs_intr_cb_hdl = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Extract the priority for the allocated interrupt/MSI. This
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * will be used later when initializing certain mutexes.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_intr_get_pri(state->hs_intrmsi_hdl[0],
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_intrmsi_pri);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the allocated interrupt/MSI handle */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) ddi_intr_free(state->hs_intrmsi_hdl[0]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor (void) ddi_cb_unregister(state->hs_intr_cb_hdl);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor state->hs_intr_cb_hdl = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Make sure the interrupt/MSI priority is below 'high level' */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (state->hs_intrmsi_pri >= ddi_intr_get_hilevel_pri()) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the allocated interrupt/MSI handle */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) ddi_intr_free(state->hs_intrmsi_hdl[0]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Get add'l capability information regarding interrupt/MSI */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_intr_get_cap(state->hs_intrmsi_hdl[0],
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_intrmsi_cap);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the allocated interrupt/MSI handle */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (void) ddi_intr_free(state->hs_intrmsi_hdl[0]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * hermon_intr_or_msi_fini()
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Context: Only called from attach() and/or detach() path contexts
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_intr_or_msi_fini(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int intr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (intr = 0; intr < state->hs_intrmsi_allocd; intr++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Free the allocated interrupt/MSI handle */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = ddi_intr_free(state->hs_intrmsi_hdl[intr]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor if (state->hs_intr_cb_hdl) {
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor (void) ddi_cb_unregister(state->hs_intr_cb_hdl);
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor state->hs_intr_cb_hdl = NULL;
17a2b317610f531d565bf4e940433aab2d9e6985Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*ARGSUSED*/
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorvoid
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_pci_capability_msix(hermon_state_t *state, ddi_acc_handle_t hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t offset)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t msix_data;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint16_t msg_cntr;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t t_offset; /* table offset */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t t_bir;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t p_offset; /* pba */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t p_bir;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int t_size; /* size in entries - each is 4 dwords */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* come in with offset pointing at the capability structure */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor msix_data = pci_config_get32(hdl, offset);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "Full cap structure dword = %X\n", msix_data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor msg_cntr = pci_config_get16(hdl, offset+2);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "MSIX msg_control = %X\n", msg_cntr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor offset += 4;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor msix_data = pci_config_get32(hdl, offset); /* table info */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor t_offset = (msix_data & 0xFFF8) >> 3;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor t_bir = msix_data & 0x07;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor offset += 4;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, " table %X --offset = %X, bir(bar) = %X\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor msix_data, t_offset, t_bir);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor msix_data = pci_config_get32(hdl, offset); /* PBA info */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor p_offset = (msix_data & 0xFFF8) >> 3;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor p_bir = msix_data & 0x07;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, " PBA %X --offset = %X, bir(bar) = %X\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor msix_data, p_offset, p_bir);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor t_size = msg_cntr & 0x7FF; /* low eleven bits */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, " table size = %X entries\n", t_size);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor offset = t_offset; /* reuse this for offset from BAR */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#ifdef HERMON_SUPPORTS_MSIX_BAR
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "First 2 table entries behind BAR2 \n");
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < 2; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (j = 0; j < 4; j++, offset += 4) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor msix_data = ddi_get32(state->hs_reg_msihdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uint32_t *)((uintptr_t)state->hs_reg_msi_baseaddr
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor + offset));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmn_err(CE_CONT, "MSI table entry %d, dword %d == %X\n",
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor i, j, msix_data);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor#endif
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * X86 fastreboot support functions.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * These functions are used to save/restore MSI-X table/PBA and also
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * to disable MSI-X interrupts in hermon_quiesce().
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* Return the message control for MSI-X */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic ushort_t
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorget_msix_ctrl(dev_info_t *dip)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ushort_t msix_ctrl = 0, caps_ctrl = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_state_t *state = ddi_get_soft_state(hermon_statep,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor DEVI(dip)->devi_instance);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t pci_cfg_hdl = hermon_get_pcihdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(pci_cfg_hdl != NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((PCI_CAP_LOCATE(pci_cfg_hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor PCI_CAP_ID_MSI_X, &caps_ctrl) == DDI_SUCCESS)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((msix_ctrl = PCI_CAP_GET16(pci_cfg_hdl, NULL, caps_ctrl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor PCI_MSIX_CTRL)) == PCI_CAP_EINVAL16)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(msix_ctrl != 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (msix_ctrl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* Return the MSI-X table size */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic size_t
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorget_msix_tbl_size(dev_info_t *dip)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ushort_t msix_ctrl = get_msix_ctrl(dip);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(msix_ctrl != 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (((msix_ctrl & PCI_MSIX_TBL_SIZE_MASK) + 1) *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor PCI_MSIX_VECTOR_SIZE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* Return the MSI-X PBA size */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic size_t
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorget_msix_pba_size(dev_info_t *dip)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ushort_t msix_ctrl = get_msix_ctrl(dip);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(msix_ctrl != 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (((msix_ctrl & PCI_MSIX_TBL_SIZE_MASK) + 64) / 64 * 8);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* Set up the MSI-X table/PBA save area */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic void
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_set_msix_info(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t rnumber, breg, nregs;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ushort_t caps_ctrl, msix_ctrl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pci_regspec_t *rp;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int reg_size, addr_space, offset, *regs_list, i;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * MSI-X BIR Index Table:
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * BAR indicator register (BIR) to Base Address register.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uchar_t pci_msix_bir_index[8] = {0x10, 0x14, 0x18, 0x1c,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor 0x20, 0x24, 0xff, 0xff};
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Fastreboot data access attribute */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_device_acc_attr_t dev_attr = {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor 0, /* version */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor DDI_STRUCTURE_LE_ACC,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor DDI_STRICTORDER_ACC, /* attr access */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor 0
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor };
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t pci_cfg_hdl = hermon_get_pcihdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(pci_cfg_hdl != NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((PCI_CAP_LOCATE(pci_cfg_hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor PCI_CAP_ID_MSI_X, &caps_ctrl) == DDI_SUCCESS)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((msix_ctrl = PCI_CAP_GET16(pci_cfg_hdl, NULL, caps_ctrl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor PCI_MSIX_CTRL)) == PCI_CAP_EINVAL16)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(msix_ctrl != 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_msix_tbl_offset = PCI_CAP_GET32(pci_cfg_hdl, NULL, caps_ctrl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor PCI_MSIX_TBL_OFFSET);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Get the BIR for MSI-X table */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor breg = pci_msix_bir_index[state->hs_msix_tbl_offset &
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor PCI_MSIX_TBL_BIR_MASK];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(breg != 0xFF);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set the MSI-X table offset */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_msix_tbl_offset = state->hs_msix_tbl_offset &
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ~PCI_MSIX_TBL_BIR_MASK;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set the MSI-X table size */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_msix_tbl_size = ((msix_ctrl & PCI_MSIX_TBL_SIZE_MASK) + 1) *
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor PCI_MSIX_VECTOR_SIZE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, state->hs_dip,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor DDI_PROP_DONTPASS, "reg", (int **)&regs_list, &nregs) !=
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor DDI_PROP_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor reg_size = sizeof (pci_regspec_t) / sizeof (int);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Check the register number for MSI-X table */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 1, rnumber = 0; i < nregs/reg_size; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor rp = (pci_regspec_t *)&regs_list[i * reg_size];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor addr_space = rp->pci_phys_hi & PCI_ADDR_MASK;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor offset = PCI_REG_REG_G(rp->pci_phys_hi);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((offset == breg) && ((addr_space == PCI_ADDR_MEM32) ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (addr_space == PCI_ADDR_MEM64))) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor rnumber = i;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(rnumber != 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_msix_tbl_rnumber = rnumber;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set device attribute version and access according to Hermon FM */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dev_attr.devacc_attr_version = hermon_devacc_attr_version(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor dev_attr.devacc_attr_access = hermon_devacc_attr_access(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Map the entire MSI-X vector table */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_regs_map_setup(state, state->hs_msix_tbl_rnumber,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (caddr_t *)&state->hs_msix_tbl_addr, state->hs_msix_tbl_offset,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_msix_tbl_size, &dev_attr,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_fm_msix_tblhdl) != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_msix_pba_offset = PCI_CAP_GET32(pci_cfg_hdl, NULL, caps_ctrl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor PCI_MSIX_PBA_OFFSET);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Get the BIR for MSI-X PBA */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor breg = pci_msix_bir_index[state->hs_msix_pba_offset &
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor PCI_MSIX_PBA_BIR_MASK];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(breg != 0xFF);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set the MSI-X PBA offset */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_msix_pba_offset = state->hs_msix_pba_offset &
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ~PCI_MSIX_PBA_BIR_MASK;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set the MSI-X PBA size */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_msix_pba_size =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ((msix_ctrl & PCI_MSIX_TBL_SIZE_MASK) + 64) / 64 * 8;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Check the register number for MSI-X PBA */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 1, rnumber = 0; i < nregs/reg_size; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor rp = (pci_regspec_t *)&regs_list[i * reg_size];
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor addr_space = rp->pci_phys_hi & PCI_ADDR_MASK;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor offset = PCI_REG_REG_G(rp->pci_phys_hi);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((offset == breg) && ((addr_space == PCI_ADDR_MEM32) ||
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (addr_space == PCI_ADDR_MEM64))) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor rnumber = i;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(rnumber != 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_msix_pba_rnumber = rnumber;
13cc0a0b8d667c14344b4ff49cc47350cd9ef182Bill Taylor ddi_prop_free(regs_list);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Map in the MSI-X Pending Bit Array */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_regs_map_setup(state, state->hs_msix_pba_rnumber,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (caddr_t *)&state->hs_msix_pba_addr, state->hs_msix_pba_offset,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_msix_pba_size, &dev_attr,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor &state->hs_fm_msix_pbahdl) != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_regs_map_free(state, &state->hs_fm_msix_tblhdl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_fm_msix_tblhdl = NULL;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set the MSI-X table save area */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_msix_tbl_entries = kmem_alloc(state->hs_msix_tbl_size,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor KM_SLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Set the MSI-X PBA save area */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_msix_pba_entries = kmem_alloc(state->hs_msix_pba_size,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor KM_SLEEP);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* Disable Hermon interrupts */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_intr_disable(hermon_state_t *state)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ushort_t msix_ctrl = 0, caps_ctrl = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t pci_cfg_hdl = hermon_get_pcihdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t msix_tblhdl = hermon_get_msix_tblhdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int i, j;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(pci_cfg_hdl != NULL && msix_tblhdl != NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(state->hs_intr_types_avail &
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (DDI_INTR_TYPE_FIXED | DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_MSIX));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Check if MSI-X interrupts are used. If so, disable MSI-X interupts.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * If not, since Hermon doesn't support MSI interrupts, assuming the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * legacy interrupt is used instead, disable the legacy interrupt.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((state->hs_cfg_profile->cp_use_msi_if_avail != 0) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (state->hs_intr_types_avail & DDI_INTR_TYPE_MSIX)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((PCI_CAP_LOCATE(pci_cfg_hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor PCI_CAP_ID_MSI_X, &caps_ctrl) == DDI_SUCCESS)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((msix_ctrl = PCI_CAP_GET16(pci_cfg_hdl, NULL,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor caps_ctrl, PCI_MSIX_CTRL)) == PCI_CAP_EINVAL16)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(msix_ctrl != 0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (!(msix_ctrl & PCI_MSIX_ENABLE_BIT))
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Clear all inums in MSI-X table */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < get_msix_tbl_size(state->hs_dip);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor i += PCI_MSIX_VECTOR_SIZE) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (j = 0; j < PCI_MSIX_VECTOR_SIZE; j += 4) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor char *addr = state->hs_msix_tbl_addr + i + j;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_put32(msix_tblhdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uint32_t *)(uintptr_t)addr, 0x0);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Disable MSI-X interrupts */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor msix_ctrl &= ~PCI_MSIX_ENABLE_BIT;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor PCI_CAP_PUT16(pci_cfg_hdl, NULL, caps_ctrl, PCI_MSIX_CTRL,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor msix_ctrl);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor } else {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint16_t cmdreg = pci_config_get16(pci_cfg_hdl, PCI_CONF_COMM);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(state->hs_intr_types_avail & DDI_INTR_TYPE_FIXED);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Disable the legacy interrupts */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor cmdreg |= PCI_COMM_INTX_DISABLE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pci_config_put16(pci_cfg_hdl, PCI_CONF_COMM, cmdreg);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor/* Hermon quiesce(9F) entry */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorstatic int
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylorhermon_quiesce(dev_info_t *dip)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor{
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_state_t *state = ddi_get_soft_state(hermon_statep,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor DEVI(dip)->devi_instance);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t pcihdl = hermon_get_pcihdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t cmdhdl = hermon_get_cmdhdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t msix_tbl_hdl = hermon_get_msix_tblhdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_acc_handle_t msix_pba_hdl = hermon_get_msix_pbahdl(state);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t sem, reset_delay = state->hs_cfg_profile->cp_sw_reset_delay;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint64_t data64;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint32_t data32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor int status, i, j, loopcnt;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor uint_t offset;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ASSERT(state != NULL);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* start fastreboot */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_quiescing = B_TRUE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
332f545bce1434913a4e2bffd942656ef0906846Eiji Ota /* If it's in maintenance mode, do nothing but return with SUCCESS */
332f545bce1434913a4e2bffd942656ef0906846Eiji Ota if (!HERMON_IS_OPERATIONAL(state->hs_operational_mode)) {
332f545bce1434913a4e2bffd942656ef0906846Eiji Ota return (DDI_SUCCESS);
332f545bce1434913a4e2bffd942656ef0906846Eiji Ota }
332f545bce1434913a4e2bffd942656ef0906846Eiji Ota
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* suppress Hermon FM ereports */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_get_state(state) & HCA_EREPORT_FM) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hermon_clr_state_nolock(state, HCA_EREPORT_FM);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Shutdown HCA ports */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_hca_ports_shutdown(state,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_cfg_profile->cp_num_ports) != HERMON_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_quiescing = B_FALSE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Close HCA */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_close_hca_cmd_post(state, HERMON_CMD_NOSLEEP_SPIN) !=
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor HERMON_CMD_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_quiescing = B_FALSE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Disable interrupts */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_intr_disable(state) != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_quiescing = B_FALSE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Query the PCI capabilities of the HCA device, but don't process
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * the VPD until after reset.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (hermon_pci_capability_list(state, pcihdl) != DDI_SUCCESS) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_quiescing = B_FALSE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Read all PCI config info (reg0...reg63). Note: According to the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * Hermon software reset application note, we should not read or
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * restore the values in reg22 and reg23.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * NOTE: For Hermon (and Arbel too) it says to restore the command
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * register LAST, and technically, you need to restore the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * PCIE Capability "device control" and "link control" (word-sized,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * at offsets 0x08 and 0x10 from the capbility ID respectively).
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * We hold off restoring the command register - offset 0x4 - till last
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* 1st, wait for the semaphore assure accessibility - per PRM */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = -1;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < NANOSEC/MICROSEC /* 1sec timeout */; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor sem = ddi_get32(cmdhdl, state->hs_cmd_regs.sw_semaphore);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (sem == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor status = 0;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor drv_usecwait(1);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Check if timeout happens */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (status == -1) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_quiescing = B_FALSE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* MSI-X interrupts are used, save the MSI-X table */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (msix_tbl_hdl && msix_pba_hdl) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* save MSI-X table */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < get_msix_tbl_size(state->hs_dip);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor i += PCI_MSIX_VECTOR_SIZE) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (j = 0; j < PCI_MSIX_VECTOR_SIZE; j += 4) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor char *addr = state->hs_msix_tbl_addr + i + j;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data32 = ddi_get32(msix_tbl_hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uint32_t *)(uintptr_t)addr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *(uint32_t *)(uintptr_t)(state->
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hs_msix_tbl_entries + i + j) = data32;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* save MSI-X PBA */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < get_msix_pba_size(state->hs_dip); i += 8) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor char *addr = state->hs_msix_pba_addr + i;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data64 = ddi_get64(msix_pba_hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uint64_t *)(uintptr_t)addr);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor *(uint64_t *)(uintptr_t)(state->
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor hs_msix_pba_entries + i) = data64;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* save PCI config space */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < HERMON_SW_RESET_NUMREGS; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((i != HERMON_SW_RESET_REG22_RSVD) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (i != HERMON_SW_RESET_REG23_RSVD)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_cfg_data[i] =
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pci_config_get32(pcihdl, i << 2);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* SW-reset HCA */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_put32(cmdhdl, state->hs_cmd_regs.sw_reset, HERMON_SW_RESET_START);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * This delay is required so as not to cause a panic here. If the
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * device is accessed too soon after reset it will not respond to
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * config cycles, causing a Master Abort and panic.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor drv_usecwait(reset_delay);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Poll waiting for the device to finish resetting */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor loopcnt = 100; /* 100 times @ 100 usec - total delay 10 msec */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor while ((pci_config_get32(pcihdl, 0) & 0x0000FFFF) != PCI_VENID_MLX) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor drv_usecwait(HERMON_SW_RESET_POLL_DELAY);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (--loopcnt == 0)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor break; /* just in case, break and go on */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (loopcnt == 0) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor state->hs_quiescing = B_FALSE;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_FAILURE);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* Restore the config info */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < HERMON_SW_RESET_NUMREGS; i++) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (i == 1) continue; /* skip the status/ctrl reg */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if ((i != HERMON_SW_RESET_REG22_RSVD) &&
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (i != HERMON_SW_RESET_REG23_RSVD)) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pci_config_put32(pcihdl, i << 2, state->hs_cfg_data[i]);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* If MSI-X interrupts are used, restore the MSI-X table */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor if (msix_tbl_hdl && msix_pba_hdl) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* restore MSI-X PBA */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < get_msix_pba_size(state->hs_dip); i += 8) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor char *addr = state->hs_msix_pba_addr + i;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data64 = *(uint64_t *)(uintptr_t)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (state->hs_msix_pba_entries + i);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_put64(msix_pba_hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uint64_t *)(uintptr_t)addr, data64);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* restore MSI-X table */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (i = 0; i < get_msix_tbl_size(state->hs_dip);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor i += PCI_MSIX_VECTOR_SIZE) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor for (j = 0; j < PCI_MSIX_VECTOR_SIZE; j += 4) {
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor char *addr = state->hs_msix_tbl_addr + i + j;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data32 = *(uint32_t *)(uintptr_t)
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (state->hs_msix_tbl_entries + i + j);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor ddi_put32(msix_tbl_hdl,
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor (uint32_t *)(uintptr_t)addr, data32);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor }
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /*
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * PCI Express Capability - we saved during capability list, and
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor * we'll restore them here.
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor offset = state->hs_pci_cap_offset;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data32 = state->hs_pci_cap_devctl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pci_config_put32(pcihdl, offset + HERMON_PCI_CAP_DEV_OFFS, data32);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor data32 = state->hs_pci_cap_lnkctl;
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pci_config_put32(pcihdl, offset + HERMON_PCI_CAP_LNK_OFFS, data32);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor /* restore the command register */
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor pci_config_put32(pcihdl, 0x04, (state->hs_cfg_data[1] | 0x0006));
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor return (DDI_SUCCESS);
9e39c5ba00a55fa05777cc94b148296af305e135Bill Taylor}