4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * CDDL HEADER START
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The contents of this file are subject to the terms of the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Common Development and Distribution License (the "License").
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * You may not use this file except in compliance with the License.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * or http://www.opensolaris.org/os/licensing.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * See the License for the specific language governing permissions
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * and limitations under the License.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * When distributing Covered Code, include this CDDL HEADER in each
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If applicable, add the following below this CDDL HEADER, with the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * fields enclosed by brackets "[]" replaced with your own identifying
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * information: Portions Copyright [yyyy] [name of copyright owner]
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * CDDL HEADER END
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister */
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister/*
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#include <sys/scsi/adapters/pmcs/pmcs.h>
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
47b47c8ce30ead58d3d8a10f770a28fd1ca95047dh#define PMCS_DRIVER_VERSION "pmcs HBA device driver"
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic char *pmcs_driver_rev = PMCS_DRIVER_VERSION;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Non-DDI Compliant stuff
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhextern char hw_serial[];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Global driver data
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid *pmcs_softc_state = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid *pmcs_iport_softstate = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Tracing and Logging info
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_tbuf_t *pmcs_tbuf = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhuint32_t pmcs_tbuf_num_elems = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_tbuf_t *pmcs_tbuf_ptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhuint32_t pmcs_tbuf_idx = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhboolean_t pmcs_tbuf_wrap = B_FALSE;
1f81b46471e38fdeb9ab74c25510b2f903f8af12David Hollisterkmutex_t pmcs_trace_lock;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If pmcs_force_syslog value is non-zero, all messages put in the trace log
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * will also be sent to system log.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint pmcs_force_syslog = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint pmcs_console = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * External References
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhextern int ncpus_online;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Local static data
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int fwlog_level = 3;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int physpeed = PHY_LINK_ALL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int phymode = PHY_LM_AUTO;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int block_mask = 0;
60aabb4ce92352f01733c518d6b6bb69e60b9113Chris Hornestatic int phymap_stable_usec = 3 * MICROSEC;
60aabb4ce92352f01733c518d6b6bb69e60b9113Chris Hornestatic int iportmap_stable_usec = 2 * MICROSEC;
60aabb4ce92352f01733c518d6b6bb69e60b9113Chris Hornestatic int iportmap_csync_usec = 20 * MICROSEC;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#ifdef DEBUG
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int debug_mask = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#else
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int debug_mask = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#endif
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#ifdef DISABLE_MSIX
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int disable_msix = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#else
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int disable_msix = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#endif
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#ifdef DISABLE_MSI
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int disable_msi = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#else
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int disable_msi = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#endif
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne/*
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne * DEBUG: testing: allow detach with an active port:
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne *
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne * # echo 'detach_driver_unconfig/W 10' | mdb -kw
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne * # echo 'scsi_hba_bus_unconfig_remove/W 1' | mdb -kw
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne * # echo 'pmcs`detach_with_active_port/W 1' | mdb -kw
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne * # modunload -i <pmcs_driver_index>
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne */
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Hornestatic int detach_with_active_port = 0;
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic uint16_t maxqdepth = 0xfffe;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Local prototypes
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_attach(dev_info_t *, ddi_attach_cmd_t);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_detach(dev_info_t *, ddi_detach_cmd_t);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_unattach(pmcs_hw_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_iport_unattach(pmcs_iport_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_add_more_chunks(pmcs_hw_t *, unsigned long);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void pmcs_watchdog(void *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_setup_intr(pmcs_hw_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_teardown_intr(pmcs_hw_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic uint_t pmcs_nonio_ix(caddr_t, caddr_t);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic uint_t pmcs_general_ix(caddr_t, caddr_t);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic uint_t pmcs_event_ix(caddr_t, caddr_t);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic uint_t pmcs_iodone_ix(caddr_t, caddr_t);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic uint_t pmcs_fatal_ix(caddr_t, caddr_t);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic uint_t pmcs_all_intr(caddr_t, caddr_t);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_quiesce(dev_info_t *dip);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic boolean_t pmcs_fabricate_wwid(pmcs_hw_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhalastatic void pmcs_create_all_phy_stats(pmcs_iport_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint pmcs_update_phy_stats(kstat_t *, int);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void pmcs_fm_fini(pmcs_hw_t *pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void pmcs_fm_init(pmcs_hw_t *pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_fm_error_cb(dev_info_t *dip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_fm_error_t *err, const void *impl_data);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Local configuration data
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic struct dev_ops pmcs_ops = {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DEVO_REV, /* devo_rev, */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 0, /* refcnt */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_no_info, /* info */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh nulldev, /* identify */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh nulldev, /* probe */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_attach, /* attach */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_detach, /* detach */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh nodev, /* reset */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh NULL, /* driver operations */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh NULL, /* bus operations */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_power, /* power management */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_quiesce /* quiesce */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh};
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic struct modldrv modldrv = {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &mod_driverops,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_DRIVER_VERSION,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pmcs_ops, /* driver ops */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh};
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic struct modlinkage modlinkage = {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh MODREV_1, &modldrv, NULL
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh};
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhconst ddi_dma_attr_t pmcs_dattr = {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DMA_ATTR_V0, /* dma_attr version */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 0x0000000000000000ull, /* dma_attr_addr_lo */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 0xFFFFFFFFFFFFFFFFull, /* dma_attr_addr_hi */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 0x00000000FFFFFFFFull, /* dma_attr_count_max */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 0x0000000000000001ull, /* dma_attr_align */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 0x00000078, /* dma_attr_burstsizes */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 0x00000001, /* dma_attr_minxfer */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 0x00000000FFFFFFFFull, /* dma_attr_maxxfer */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 0x00000000FFFFFFFFull, /* dma_attr_seg */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 1, /* dma_attr_sgllen */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 512, /* dma_attr_granular */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 0 /* dma_attr_flags */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh};
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic ddi_device_acc_attr_t rattr = {
837c1ac4e72b7d86278cca88b1075af557f7d161Stephen Hanson DDI_DEVICE_ATTR_V1,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_STRUCTURE_LE_ACC,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_STRICTORDER_ACC,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_DEFAULT_ACC
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh};
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Attach/Detach functions
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh_init(void)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int ret;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ret = ddi_soft_state_init(&pmcs_softc_state, sizeof (pmcs_hw_t), 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ret != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cmn_err(CE_WARN, "?soft state init failed for pmcs");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ret);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((ret = scsi_hba_init(&modlinkage)) != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cmn_err(CE_WARN, "?scsi_hba_init failed for pmcs");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_fini(&pmcs_softc_state);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ret);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Allocate soft state for iports
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ret = ddi_soft_state_init(&pmcs_iport_softstate,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sizeof (pmcs_iport_t), 2);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ret != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cmn_err(CE_WARN, "?iport soft state init failed for pmcs");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_fini(&pmcs_softc_state);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ret);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ret = mod_install(&modlinkage);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ret != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cmn_err(CE_WARN, "?mod_install failed for pmcs (%d)", ret);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_hba_fini(&modlinkage);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_fini(&pmcs_iport_softstate);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_fini(&pmcs_softc_state);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ret);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Initialize the global trace lock */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&pmcs_trace_lock, NULL, MUTEX_DRIVER, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh_fini(void)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int ret;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((ret = mod_remove(&modlinkage)) != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ret);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_hba_fini(&modlinkage);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Free pmcs log buffer and destroy the global lock */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_tbuf) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_free(pmcs_tbuf,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_tbuf_num_elems * sizeof (pmcs_tbuf_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_tbuf = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_destroy(&pmcs_trace_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_fini(&pmcs_iport_softstate);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_fini(&pmcs_softc_state);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh_info(struct modinfo *modinfop)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (mod_info(&modlinkage, modinfop));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_iport_attach(dev_info_t *dip)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_iport_t *iport;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_hba_tran_t *tran;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh void *ua_priv = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char *iport_ua;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char *init_port;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int hba_inst;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int inst;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh hba_inst = ddi_get_instance(ddi_get_parent(dip));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh inst = ddi_get_instance(dip);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp = ddi_get_soft_state(pmcs_softc_state, hba_inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp == NULL) {
a25672a1f5bcd6aa4bbce28adab51d84ae202323David Hollister cmn_err(CE_WARN, "%s: No HBA softstate for instance %d",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((pwp->state == STATE_UNPROBING) || (pwp->state == STATE_DEAD)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((iport_ua = scsi_hba_iport_unit_address(dip)) == NULL) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: invoked with NULL unit address, inst (%d)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_soft_state_zalloc(pmcs_iport_softstate, inst) != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Failed to alloc soft state for iport %d", inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport = ddi_get_soft_state(pmcs_iport_softstate, inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (iport == NULL) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "cannot get iport soft state");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto iport_attach_fail1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&iport->lock, NULL, MUTEX_DRIVER,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_INTR_PRI(pwp->intr_pri));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_init(&iport->refcnt_cv, NULL, CV_DEFAULT, NULL);
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler cv_init(&iport->smp_cv, NULL, CV_DEFAULT, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&iport->refcnt_lock, NULL, MUTEX_DRIVER,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_INTR_PRI(pwp->intr_pri));
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler mutex_init(&iport->smp_lock, NULL, MUTEX_DRIVER,
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler DDI_INTR_PRI(pwp->intr_pri));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Set some data on the iport handle */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport->dip = dip;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport->pwp = pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Dup the UA into the iport handle */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport->ua = strdup(iport_ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tran = (scsi_hba_tran_t *)ddi_get_driver_private(dip);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tran->tran_hba_private = iport;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh list_create(&iport->phys, sizeof (pmcs_phy_t),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh offsetof(pmcs_phy_t, list_node));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If our unit address is active in the phymap, configure our
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * iport's phylist.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ua_priv = sas_phymap_lookup_uapriv(pwp->hss_phymap, iport->ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ua_priv) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Non-NULL private data indicates the unit address is active */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport->ua_state = UA_ACTIVE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_iport_configure_phys(iport) != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: failed to "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "configure phys on iport handle (0x%p), "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh " unit address [%s]", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)iport, iport_ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto iport_attach_fail2;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport->ua_state = UA_INACTIVE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Allocate string-based soft state pool for targets */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport->tgt_sstate = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_soft_state_bystr_init(&iport->tgt_sstate,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sizeof (pmcs_xscsi_t), PMCS_TGT_SSTATE_SZ) != 0) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "cannot get iport tgt soft state");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto iport_attach_fail2;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Create this iport's target map */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_iport_tgtmap_create(iport) == B_FALSE) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Failed to create tgtmap on iport %d", inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto iport_attach_fail3;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Set up the 'initiator-port' DDI property on this iport */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh init_port = kmem_zalloc(PMCS_MAX_UA_SIZE, KM_SLEEP);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->separate_ports) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: separate ports not supported", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Set initiator-port value to the HBA's base WWN */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) scsi_wwn_to_wwnstr(pwp->sas_wwns[0], 1,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh init_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_enter(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_smhba_add_iport_prop(iport, DATA_TYPE_STRING,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCSI_ADDR_PROP_INITIATOR_PORT, init_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_free(init_port, PMCS_MAX_UA_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Set up a 'num-phys' DDI property for the iport node */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_smhba_add_iport_prop(iport, DATA_TYPE_INT32, PMCS_NUM_PHYS,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &iport->nphy);
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_exit(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Create kstats for each of the phys in this port */
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala pmcs_create_all_phy_stats(iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Insert this iport handle into our list and set
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * iports_attached on the HBA node.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rw_enter(&pwp->iports_lock, RW_WRITER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(!list_link_active(&iport->list_node));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh list_insert_tail(&pwp->iports, iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->iports_attached = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->num_iports++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rw_exit(&pwp->iports_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_IPORT, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "iport%d attached", inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_report_dev(dip);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* teardown and fail */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhiport_attach_fail3:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_bystr_fini(&iport->tgt_sstate);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhiport_attach_fail2:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh list_destroy(&iport->phys);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh strfree(iport->ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_destroy(&iport->refcnt_lock);
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler mutex_destroy(&iport->smp_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_destroy(&iport->refcnt_cv);
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler cv_destroy(&iport->smp_cv);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_destroy(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhiport_attach_fail1:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_free(pmcs_iport_softstate, inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_hba_tran_t *tran;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char chiprev, *fwsupport, hw_rev[24], fw_rev[24];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh off_t set3size;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int inst, i;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int sm_hba = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int protocol = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int num_phys = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *phyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t num_threads;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char buf[64];
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister char *fwl_file;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (cmd) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case DDI_ATTACH:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case DDI_PM_RESUME:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case DDI_RESUME:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tran = (scsi_hba_tran_t *)ddi_get_driver_private(dip);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!tran) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* No DDI_?_RESUME on iport nodes */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (scsi_hba_iport_unit_address(dip) != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp = TRAN2PMC(tran);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->suspended = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->tq) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_taskq_resume(pwp->tq);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If this is an iport node, invoke iport attach.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (scsi_hba_iport_unit_address(dip) != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (pmcs_iport_attach(dip));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * From here on is attach for the HBA node
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#ifdef DEBUG
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Check to see if this unit is to be disabled. We can't disable
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * on a per-iport node. It's either the entire HBA or nothing.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(buf, sizeof (buf),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "disable-instance-%d", ddi_get_instance(dip));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_prop_get_int(DDI_DEV_T_ANY, dip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, buf, 0)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cmn_err(CE_NOTE, "pmcs%d: disabled by configuration",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_get_instance(dip));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#endif
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Allocate softstate
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh inst = ddi_get_instance(dip);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_soft_state_zalloc(pmcs_softc_state, inst) != DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cmn_err(CE_WARN, "pmcs%d: Failed to alloc soft state", inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp = ddi_get_soft_state(pmcs_softc_state, inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cmn_err(CE_WARN, "pmcs%d: cannot get soft state", inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_free(pmcs_softc_state, inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->dip = dip;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INIT(&pwp->dq);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INIT(&pwp->cq);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INIT(&pwp->wf);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INIT(&pwp->pf);
32b54db7d7ecdb10cc3178edf2c480c6dc5c5559Jesse Butler
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
32b54db7d7ecdb10cc3178edf2c480c6dc5c5559Jesse Butler * Create the list for iports and init its lock.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh list_create(&pwp->iports, sizeof (pmcs_iport_t),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh offsetof(pmcs_iport_t, list_node));
32b54db7d7ecdb10cc3178edf2c480c6dc5c5559Jesse Butler rw_init(&pwp->iports_lock, NULL, RW_DRIVER, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->state = STATE_PROBING;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Get driver.conf properties
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->debug_mask = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-debug-mask",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh debug_mask);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->phyid_block_mask = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-phyid-block-mask",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh block_mask);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->physpeed = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-physpeed", physpeed);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->phymode = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-phymode", phymode);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->fwlog = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-fwlog", fwlog_level);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->fwlog > PMCS_FWLOG_MAX) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->fwlog = PMCS_FWLOG_MAX;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, dip, 0, "pmcs-fwlogfile",
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister &fwl_file) == DDI_SUCCESS)) {
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister if (snprintf(pwp->fwlogfile_aap1, MAXPATHLEN, "%s%d-aap1.0",
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister fwl_file, ddi_get_instance(dip)) > MAXPATHLEN) {
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister pwp->fwlogfile_aap1[0] = '\0';
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister pwp->fwlogfile_iop[0] = '\0';
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister } else if (snprintf(pwp->fwlogfile_iop, MAXPATHLEN,
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister "%s%d-iop.0", fwl_file,
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister ddi_get_instance(dip)) > MAXPATHLEN) {
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister pwp->fwlogfile_aap1[0] = '\0';
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister pwp->fwlogfile_iop[0] = '\0';
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister }
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister ddi_prop_free(fwl_file);
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister } else {
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister pwp->fwlogfile_aap1[0] = '\0';
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister pwp->fwlogfile_iop[0] = '\0';
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister pwp->open_retry_interval = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-open-retry-interval",
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister OPEN_RETRY_INTERVAL_DEF);
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister if (pwp->open_retry_interval > OPEN_RETRY_INTERVAL_MAX) {
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister pwp->open_retry_interval = OPEN_RETRY_INTERVAL_MAX;
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister }
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pmcs_trace_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_tbuf == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Allocate trace buffer */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_tbuf_num_elems = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-tbuf-num-elems",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_TBUF_NUM_ELEMS_DEF);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((pmcs_tbuf_num_elems == DDI_PROP_NOT_FOUND) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pmcs_tbuf_num_elems == 0)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_tbuf_num_elems = PMCS_TBUF_NUM_ELEMS_DEF;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_tbuf = kmem_zalloc(pmcs_tbuf_num_elems *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sizeof (pmcs_tbuf_t), KM_SLEEP);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_tbuf_ptr = pmcs_tbuf;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_tbuf_idx = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pmcs_trace_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister if (pwp->fwlog && strlen(pwp->fwlogfile_aap1) > 0) {
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister "%s: firmware event log files: %s, %s", __func__,
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister pwp->fwlogfile_aap1, pwp->fwlogfile_iop);
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister pwp->fwlog_file = 1;
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister } else {
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister if (pwp->fwlog == 0) {
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister "%s: No firmware event log will be written "
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister "(event log disabled)", __func__);
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister } else {
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister "%s: No firmware event log will be written "
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister "(no filename configured - too long?)", __func__);
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister }
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister pwp->fwlog_file = 0;
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister }
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh disable_msix = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-disable-msix",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh disable_msix);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh disable_msi = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-disable-msi",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh disable_msi);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh maxqdepth = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-maxqdepth", maxqdepth);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->fw_force_update = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-fw-force-update", 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->fw_force_update == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->fw_disable_update = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "pmcs-fw-disable-update", 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->ioq_depth = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, "pmcs-num-io-qentries",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_NQENTRY);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Initialize FMA
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->dev_acc_attr = pwp->reg_acc_attr = rattr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->iqp_dma_attr = pwp->oqp_dma_attr =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->regdump_dma_attr = pwp->cip_dma_attr =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->fwlog_dma_attr = pmcs_dattr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, pwp->dip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_PROP_NOTPROM | DDI_PROP_DONTPASS, "fm-capable",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_fm_init(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Map registers
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pci_config_setup(dip, &pwp->pci_acc_handle)) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "pci config setup failed");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_free(pmcs_softc_state, inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Get the size of register set 3.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_dev_regsize(dip, PMCS_REGSET_3, &set3size) != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "unable to get size of register set %d", PMCS_REGSET_3);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pci_config_teardown(&pwp->pci_acc_handle);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_free(pmcs_softc_state, inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Map registers
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->reg_acc_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_regs_map_setup(dip, PMCS_REGSET_0, (caddr_t *)&pwp->msg_regs,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 0, 0, &pwp->reg_acc_attr, &pwp->msg_acc_handle)) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "failed to map Message Unit registers");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pci_config_teardown(&pwp->pci_acc_handle);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_free(pmcs_softc_state, inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_regs_map_setup(dip, PMCS_REGSET_1, (caddr_t *)&pwp->top_regs,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 0, 0, &pwp->reg_acc_attr, &pwp->top_acc_handle)) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "failed to map TOP registers");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_regs_map_free(&pwp->msg_acc_handle);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pci_config_teardown(&pwp->pci_acc_handle);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_free(pmcs_softc_state, inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_regs_map_setup(dip, PMCS_REGSET_2, (caddr_t *)&pwp->gsm_regs,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 0, 0, &pwp->reg_acc_attr, &pwp->gsm_acc_handle)) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "failed to map GSM registers");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_regs_map_free(&pwp->top_acc_handle);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_regs_map_free(&pwp->msg_acc_handle);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pci_config_teardown(&pwp->pci_acc_handle);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_free(pmcs_softc_state, inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_regs_map_setup(dip, PMCS_REGSET_3, (caddr_t *)&pwp->mpi_regs,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 0, 0, &pwp->reg_acc_attr, &pwp->mpi_acc_handle)) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "failed to map MPI registers");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_regs_map_free(&pwp->top_acc_handle);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_regs_map_free(&pwp->gsm_acc_handle);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_regs_map_free(&pwp->msg_acc_handle);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pci_config_teardown(&pwp->pci_acc_handle);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_free(pmcs_softc_state, inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->mpibar =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((5U << 2) + 0x10) << PMCS_MSGU_MPI_BAR_SHIFT) | set3size;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Make sure we can support this card.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->chiprev = pmcs_rd_topunit(pwp, PMCS_DEVICE_REVISION);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (pwp->chiprev) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_PM8001_REV_A:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_PM8001_REV_B:
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Rev A/B Card no longer supported");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto failure;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_PM8001_REV_C:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Unknown chip revision (%d)", pwp->chiprev);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto failure;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Allocate DMA addressable area for Inbound and Outbound Queue indices
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * that the chip needs to access plus a space for scratch usage
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->cip_dma_attr.dma_attr_align = sizeof (uint32_t);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_dma_setup(pwp, &pwp->cip_dma_attr, &pwp->cip_acchdls,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->cip_handles, ptob(1), (caddr_t *)&pwp->cip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->ciaddr) == B_FALSE) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Failed to setup DMA for index/scratch");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto failure;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(pwp->cip, ptob(1));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->scratch = &pwp->cip[PMCS_INDICES_SIZE];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->scratch_dma = pwp->ciaddr + PMCS_INDICES_SIZE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Allocate DMA S/G list chunks
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_add_more_chunks(pwp, ptob(1) * PMCS_MIN_CHUNK_PAGES);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Allocate a DMA addressable area for the firmware log (if needed)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->fwlog) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Align to event log header and entry size
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->fwlog_dma_attr.dma_attr_align = 32;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_dma_setup(pwp, &pwp->fwlog_dma_attr,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->fwlog_acchdl,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->fwlog_hndl, PMCS_FWLOG_SIZE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (caddr_t *)&pwp->fwlogp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->fwaddr) == B_FALSE) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Failed to setup DMA for fwlog area");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->fwlog = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(pwp->fwlogp, PMCS_FWLOG_SIZE);
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister pwp->fwlogp_aap1 = (pmcs_fw_event_hdr_t *)pwp->fwlogp;
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister pwp->fwlogp_iop = (pmcs_fw_event_hdr_t *)((void *)
9719310a57482091af0a7f0ee31b5e2eec35f154David Hollister ((caddr_t)pwp->fwlogp + (PMCS_FWLOG_SIZE / 2)));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->flash_chunk_addr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->regdump_dma_attr.dma_attr_align = PMCS_FLASH_CHUNK_SIZE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_dma_setup(pwp, &pwp->regdump_dma_attr,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->regdump_acchdl,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->regdump_hndl, PMCS_FLASH_CHUNK_SIZE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (caddr_t *)&pwp->flash_chunkp, &pwp->flash_chunk_addr) ==
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh B_FALSE) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Failed to setup DMA for register dump area");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto failure;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(pwp->flash_chunkp, PMCS_FLASH_CHUNK_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * More bits of local initialization...
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->tq = ddi_taskq_create(dip, "_tq", 4, TASKQ_DEFAULTPRI, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->tq == NULL) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "unable to create worker taskq");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto failure;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Cache of structures for dealing with I/O completion callbacks.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(buf, sizeof (buf), "pmcs_iocomp_cb_cache%d", inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->iocomp_cb_cache = kmem_cache_create(buf,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sizeof (pmcs_iocomp_cb_t), 16, NULL, NULL, NULL, NULL, NULL, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Cache of PHY structures
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(buf, sizeof (buf), "pmcs_phy_cache%d", inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->phy_cache = kmem_cache_create(buf, sizeof (pmcs_phy_t), 8,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_constructor, pmcs_phy_destructor, NULL, (void *)pwp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh NULL, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Allocate space for the I/O completion threads
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh num_threads = ncpus_online;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (num_threads > PMCS_MAX_CQ_THREADS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh num_threads = PMCS_MAX_CQ_THREADS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->cq_info.cq_threads = num_threads;
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne pwp->cq_info.cq_thr_info = kmem_zalloc(
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne sizeof (pmcs_cq_thr_info_t) * pwp->cq_info.cq_threads, KM_SLEEP);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->cq_info.cq_next_disp_thr = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->cq_info.cq_stop = B_FALSE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Set the quantum value in clock ticks for the I/O interrupt
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * coalescing timer.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->io_intr_coal.quantum = drv_usectohz(PMCS_QUANTUM_TIME_USECS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We have a delicate dance here. We need to set up
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * interrupts so we know how to set up some OQC
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * tables. However, while we're setting up table
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * access, we may need to flash new firmware and
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * reset the card, which will take some finessing.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Set up interrupts here.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (pmcs_setup_intr(pwp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case 0:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case EIO:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->stuck = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* FALLTHROUGH */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto failure;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Set these up now becuase they are used to initialize the OQC tables.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we have MSI or MSI-X interrupts set up and we have enough
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * vectors for each OQ, the Outbound Queue vectors can all be the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * same as the appropriate interrupt routine will have been called
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * and the doorbell register automatically cleared.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This keeps us from having to check the Outbound Doorbell register
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * when the routines for these interrupts are called.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we have Legacy INT-X interrupts set up or we didn't have enough
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * MSI/MSI-X vectors to uniquely identify each OQ, we point these
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * vectors to the bits we would like to have set in the Outbound
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Doorbell register because pmcs_all_intr will read the doorbell
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * register to find out why we have an interrupt and write the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * corresponding 'clear' bit for that interrupt.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (pwp->intr_cnt) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case 1:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Only one vector, so we must check all OQs for MSI. For
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * INT-X, there's only one vector anyway, so we can just
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * use the outbound queue bits to keep from having to
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * check each queue for each interrupt.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->int_type == PMCS_INT_FIXED) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->oqvec[PMCS_OQ_IODONE] = PMCS_OQ_IODONE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->oqvec[PMCS_OQ_GENERAL] = PMCS_OQ_GENERAL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->oqvec[PMCS_OQ_EVENTS] = PMCS_OQ_EVENTS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->oqvec[PMCS_OQ_IODONE] = PMCS_OQ_IODONE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->oqvec[PMCS_OQ_GENERAL] = PMCS_OQ_IODONE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->oqvec[PMCS_OQ_EVENTS] = PMCS_OQ_IODONE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case 2:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* With 2, we can at least isolate IODONE */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->oqvec[PMCS_OQ_IODONE] = PMCS_OQ_IODONE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->oqvec[PMCS_OQ_GENERAL] = PMCS_OQ_GENERAL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->oqvec[PMCS_OQ_EVENTS] = PMCS_OQ_GENERAL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case 4:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* With 4 vectors, everybody gets one */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->oqvec[PMCS_OQ_IODONE] = PMCS_OQ_IODONE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->oqvec[PMCS_OQ_GENERAL] = PMCS_OQ_GENERAL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->oqvec[PMCS_OQ_EVENTS] = PMCS_OQ_EVENTS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Do the first part of setup
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_setup(pwp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto failure;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_report_fwversion(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Now do some additonal allocations based upon information
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * gathered during MPI setup.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->root_phys = kmem_zalloc(pwp->nphy * sizeof (pmcs_phy_t), KM_SLEEP);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pwp->nphy < SAS2_PHYNUM_MAX);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = pwp->root_phys;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < pwp->nphy; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (i < pwp->nphy-1) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp->sibling = (phyp + 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&phyp->phy_lock, NULL, MUTEX_DRIVER,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_INTR_PRI(pwp->intr_pri));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp->phynum = i & SAS2_PHYNUM_MASK;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_name(pwp, phyp, phyp->path, sizeof (phyp->path));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp->pwp = pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp->device_id = PMCS_INVALID_DEVICE_ID;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana phyp->portid = PMCS_PHY_INVALID_PORT_ID;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->work = kmem_zalloc(pwp->max_cmd * sizeof (pmcwork_t), KM_SLEEP);
978d7443a924cda8208d6a10e72be89383bc7becSrikanth Suravajhala for (i = 0; i < pwp->max_cmd; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcwork_t *pwrk = &pwp->work[i];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&pwrk->lock, NULL, MUTEX_DRIVER,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_INTR_PRI(pwp->intr_pri));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_init(&pwrk->sleep_cv, NULL, CV_DRIVER, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_TAIL(&pwp->wf, pwrk, next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->targets = (pmcs_xscsi_t **)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_zalloc(pwp->max_dev * sizeof (pmcs_xscsi_t *), KM_SLEEP);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->iqpt = (pmcs_iqp_trace_t *)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_zalloc(sizeof (pmcs_iqp_trace_t), KM_SLEEP);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->iqpt->head = kmem_zalloc(PMCS_IQP_TRACE_BUFFER_SIZE, KM_SLEEP);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->iqpt->curpos = pwp->iqpt->head;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->iqpt->size_left = PMCS_IQP_TRACE_BUFFER_SIZE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Start MPI communication.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_start_mpi(pwp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_soft_reset(pwp, B_FALSE)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto failure;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pwp->last_reset_reason = PMCS_LAST_RST_ATTACH;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Do some initial acceptance tests.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This tests interrupts and queues.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_echo_test(pwp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto failure;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Read VPD - if it exists */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_get_nvmd(pwp, PMCS_NVMD_VPD, PMCIN_NVMD_VPD, 0, NULL, 0)) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: Unable to read VPD: "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "attempting to fabricate", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * When we release, this must goto failure and the call
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * to pmcs_fabricate_wwid is removed.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* goto failure; */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!pmcs_fabricate_wwid(pwp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto failure;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We're now officially running
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->state = STATE_RUNNING;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Check firmware versions and load new firmware
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * if needed and reset.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_firmware_update(pwp)) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: Firmware update failed", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto failure;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Create completion threads.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < pwp->cq_info.cq_threads; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->cq_info.cq_thr_info[i].cq_pwp = pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->cq_info.cq_thr_info[i].cq_thread =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh thread_create(NULL, 0, pmcs_scsa_cq_run,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->cq_info.cq_thr_info[i], 0, &p0, TS_RUN, minclsyspri);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Create one thread to deal with the updating of the interrupt
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * coalescing timer.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->ict_thread = thread_create(NULL, 0, pmcs_check_intr_coal,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp, 0, &p0, TS_RUN, minclsyspri);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Kick off the watchdog
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->wdhandle = timeout(pmcs_watchdog, pwp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usectohz(PMCS_WATCH_INTERVAL));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Do the SCSI attachment code (before starting phys)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_scsa_init(pwp, &pmcs_dattr)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto failure;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->hba_attached = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Check all acc & dma handles allocated in attach */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_check_acc_dma_handle(pwp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_fm_service_impact(pwp->dip, DDI_SERVICE_LOST);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto failure;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne * Create the iportmap for this HBA instance
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne if (scsi_hba_iportmap_create(dip, iportmap_csync_usec,
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne iportmap_stable_usec, &pwp->hss_iportmap) != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne "%s: pmcs%d iportmap_create failed", __func__, inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto failure;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne ASSERT(pwp->hss_iportmap);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne * Create the phymap for this HBA instance
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne if (sas_phymap_create(dip, phymap_stable_usec, PHYMAP_MODE_SIMPLE, NULL,
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne pwp, pmcs_phymap_activate, pmcs_phymap_deactivate,
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne &pwp->hss_phymap) != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne "%s: pmcs%d phymap_create failed", __func__, inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto failure;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne ASSERT(pwp->hss_phymap);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Start the PHYs.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_start_phys(pwp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto failure;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * From this point on, we can't fail.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_report_dev(dip);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* SM-HBA */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_smhba_add_hba_prop(pwp, DATA_TYPE_INT32, PMCS_SMHBA_SUPPORTED,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &sm_hba);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* SM-HBA */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_smhba_add_hba_prop(pwp, DATA_TYPE_STRING, PMCS_DRV_VERSION,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_driver_rev);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* SM-HBA */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh chiprev = 'A' + pwp->chiprev;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(hw_rev, 2, "%s", &chiprev);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_smhba_add_hba_prop(pwp, DATA_TYPE_STRING, PMCS_HWARE_VERSION,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh hw_rev);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* SM-HBA */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (PMCS_FW_TYPE(pwp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_FW_TYPE_RELEASED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fwsupport = "Released";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_FW_TYPE_DEVELOPMENT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fwsupport = "Development";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_FW_TYPE_ALPHA:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fwsupport = "Alpha";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_FW_TYPE_BETA:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fwsupport = "Beta";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fwsupport = "Special";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(fw_rev, sizeof (fw_rev), "%x.%x.%x %s",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_FW_MAJOR(pwp), PMCS_FW_MINOR(pwp), PMCS_FW_MICRO(pwp),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fwsupport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_smhba_add_hba_prop(pwp, DATA_TYPE_STRING, PMCS_FWARE_VERSION,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fw_rev);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* SM-HBA */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh num_phys = pwp->nphy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_smhba_add_hba_prop(pwp, DATA_TYPE_INT32, PMCS_NUM_PHYS_HBA,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &num_phys);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* SM-HBA */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh protocol = SAS_SSP_SUPPORT | SAS_SATA_SUPPORT | SAS_SMP_SUPPORT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_smhba_add_hba_prop(pwp, DATA_TYPE_INT32, PMCS_SUPPORTED_PROTOCOL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &protocol);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister /* Receptacle properties (FMA) */
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister pwp->recept_labels[0] = PMCS_RECEPT_LABEL_0;
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister pwp->recept_pm[0] = PMCS_RECEPT_PM_0;
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister pwp->recept_labels[1] = PMCS_RECEPT_LABEL_1;
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister pwp->recept_pm[1] = PMCS_RECEPT_PM_1;
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister if (ddi_prop_update_string_array(DDI_DEV_T_NONE, dip,
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister SCSI_HBA_PROP_RECEPTACLE_LABEL, &pwp->recept_labels[0],
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister PMCS_NUM_RECEPTACLES) != DDI_PROP_SUCCESS) {
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister "%s: failed to create %s property", __func__,
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister "receptacle-label");
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister }
1f81b46471e38fdeb9ab74c25510b2f903f8af12David Hollister if (ddi_prop_update_string_array(DDI_DEV_T_NONE, dip,
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister SCSI_HBA_PROP_RECEPTACLE_PM, &pwp->recept_pm[0],
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister PMCS_NUM_RECEPTACLES) != DDI_PROP_SUCCESS) {
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister "%s: failed to create %s property", __func__,
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister "receptacle-pm");
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister }
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhfailure:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_unattach(pwp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->stuck = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int inst = ddi_get_instance(dip);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_iport_t *iport = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_hba_tran_t *tran;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (scsi_hba_iport_unit_address(dip) != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* iport node */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport = ddi_get_soft_state(pmcs_iport_softstate, inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (iport == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp = iport->pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* hba node */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp = (pmcs_hw_t *)ddi_get_soft_state(pmcs_softc_state, inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (cmd) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case DDI_DETACH:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (iport) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* iport detach */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_iport_unattach(iport)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "iport%d detached", inst);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* HBA detach */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_unattach(pwp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case DDI_SUSPEND:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case DDI_PM_SUSPEND:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* No DDI_SUSPEND on iport nodes */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (iport) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->stuck) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tran = (scsi_hba_tran_t *)ddi_get_driver_private(dip);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!tran) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp = TRAN2PMC(tran);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->tq) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_taskq_suspend(pwp->tq);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->suspended = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "PMC8X6G suspending");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_iport_unattach(pmcs_iport_t *iport)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = iport->pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * First, check if there are still any configured targets on this
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * iport. If so, we fail detach.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_iport_has_targets(pwp, iport)) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_IPORT, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "iport%d detach failure: iport has targets (luns)",
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh ddi_get_instance(iport->dip));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Remove this iport from our list if it is inactive in the phymap.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rw_enter(&pwp->iports_lock, RW_WRITER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne if ((iport->ua_state == UA_ACTIVE) &&
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne (detach_with_active_port == 0)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rw_exit(&pwp->iports_lock);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_IPORT, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "iport%d detach failure: "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "iport unit address active in phymap",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_get_instance(iport->dip));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* If it's our only iport, clear iports_attached */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pwp->num_iports >= 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (--pwp->num_iports == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->iports_attached = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(list_link_active(&iport->list_node));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh list_remove(&pwp->iports, iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rw_exit(&pwp->iports_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We have removed the iport handle from the HBA's iports list,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * there will be no new references to it. Two things must be
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * guarded against here. First, we could have PHY up events,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * adding themselves to the iport->phys list and grabbing ref's
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * on our iport handle. Second, we could have existing references
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * to this iport handle from a point in time prior to the list
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * removal above.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * So first, destroy the phys list. Remove any phys that have snuck
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * in after the phymap deactivate, dropping the refcnt accordingly.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If these PHYs are still up if and when the phymap reactivates
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * (i.e. when this iport reattaches), we'll populate the list with
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * them and bump the refcnt back up.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_remove_phy_from_iport(iport, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(list_is_empty(&iport->phys));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh list_destroy(&iport->phys);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Second, wait for any other references to this iport to be
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * dropped, then continue teardown.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&iport->refcnt_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (iport->refcnt != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_wait(&iport->refcnt_cv, &iport->refcnt_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&iport->refcnt_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Destroy the iport target map */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_iport_tgtmap_destroy(iport) == B_FALSE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Free the tgt soft state */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (iport->tgt_sstate != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_bystr_fini(&iport->tgt_sstate);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Free our unit address string */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh strfree(iport->ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Finish teardown and free the softstate */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_destroy(&iport->refcnt_lock);
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler mutex_destroy(&iport->smp_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(iport->refcnt == 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_destroy(&iport->refcnt_cv);
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler cv_destroy(&iport->smp_cv);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_destroy(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_free(pmcs_iport_softstate, ddi_get_instance(iport->dip));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_unattach(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int i;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh enum pwpstate curstate;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_cq_thr_info_t *cqti;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Tear down the interrupt infrastructure.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_teardown_intr(pwp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->stuck = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->intr_cnt = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Grab a lock, if initted, to set state.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->locks_initted) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->state != STATE_DEAD) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->state = STATE_UNPROBING;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh curstate = pwp->state;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Stop the I/O completion threads.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->cq_info.cq_stop = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < pwp->cq_info.cq_threads; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->cq_info.cq_thr_info[i].cq_thread) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cqti = &pwp->cq_info.cq_thr_info[i];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&cqti->cq_thr_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_signal(&cqti->cq_cv);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&cqti->cq_thr_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh thread_join(cqti->cq_thread->t_did);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->cq_lock);
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne kmem_free(pwp->cq_info.cq_thr_info,
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne sizeof (pmcs_cq_thr_info_t) * pwp->cq_info.cq_threads);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Stop the interrupt coalescing timer thread
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->ict_thread) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->ict_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->io_intr_coal.stop_thread = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_signal(&pwp->ict_cv);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->ict_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh thread_join(pwp->ict_thread->t_did);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->state != STATE_DEAD) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->state = STATE_UNPROBING;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh curstate = pwp->state;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Make sure that any pending watchdog won't
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * be called from this point on out.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) untimeout(pwp->wdhandle);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * After the above action, the watchdog
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * timer that starts up the worker task
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * may trigger but will exit immediately
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * on triggering.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Now that this is done, we can destroy
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the task queue, which will wait if we're
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * running something on it.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->tq) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_taskq_destroy(pwp->tq);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->tq = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_fm_fini(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->hba_attached) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) scsi_hba_detach(pwp->dip);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->hba_attached = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the chip hasn't been marked dead, shut it down now
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * to bring it back to a known state without attempting
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * a soft reset.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (curstate != STATE_DEAD && pwp->locks_initted) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * De-register all registered devices
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_deregister_devices(pwp, pwp->root_phys);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Stop all the phys.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_stop_phys(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Shut Down Message Passing
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_stop_mpi(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Reset chip
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_soft_reset(pwp, B_FALSE);
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pwp->last_reset_reason = PMCS_LAST_RST_DETACH;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Turn off interrupts on the chip
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->mpi_acc_handle) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_MASK, 0xffffffff);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
32b54db7d7ecdb10cc3178edf2c480c6dc5c5559Jesse Butler if (pwp->hss_phymap != NULL) {
32b54db7d7ecdb10cc3178edf2c480c6dc5c5559Jesse Butler /* Destroy the phymap */
32b54db7d7ecdb10cc3178edf2c480c6dc5c5559Jesse Butler sas_phymap_destroy(pwp->hss_phymap);
32b54db7d7ecdb10cc3178edf2c480c6dc5c5559Jesse Butler }
32b54db7d7ecdb10cc3178edf2c480c6dc5c5559Jesse Butler
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne if (pwp->hss_iportmap != NULL) {
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne /* Destroy the iportmap */
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne scsi_hba_iportmap_destroy(pwp->hss_iportmap);
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne }
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne
32b54db7d7ecdb10cc3178edf2c480c6dc5c5559Jesse Butler /* Destroy the iports lock and list */
32b54db7d7ecdb10cc3178edf2c480c6dc5c5559Jesse Butler rw_destroy(&pwp->iports_lock);
32b54db7d7ecdb10cc3178edf2c480c6dc5c5559Jesse Butler ASSERT(list_is_empty(&pwp->iports));
32b54db7d7ecdb10cc3178edf2c480c6dc5c5559Jesse Butler list_destroy(&pwp->iports);
32b54db7d7ecdb10cc3178edf2c480c6dc5c5559Jesse Butler
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Free DMA handles and associated consistent memory
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->regdump_hndl) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_dma_unbind_handle(pwp->regdump_hndl) != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "Condition check failed "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "at %s():%d", __func__, __LINE__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_dma_free_handle(&pwp->regdump_hndl);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_dma_mem_free(&pwp->regdump_acchdl);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->regdump_hndl = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->fwlog_hndl) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_dma_unbind_handle(pwp->fwlog_hndl) != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "Condition check failed "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "at %s():%d", __func__, __LINE__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_dma_free_handle(&pwp->fwlog_hndl);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_dma_mem_free(&pwp->fwlog_acchdl);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->fwlog_hndl = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->cip_handles) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_dma_unbind_handle(pwp->cip_handles) != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "Condition check failed "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "at %s():%d", __func__, __LINE__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_dma_free_handle(&pwp->cip_handles);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_dma_mem_free(&pwp->cip_acchdls);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->cip_handles = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < PMCS_NOQ; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->oqp_handles[i]) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_dma_unbind_handle(pwp->oqp_handles[i]) !=
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "Condition check failed at %s():%d",
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh __func__, __LINE__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_dma_free_handle(&pwp->oqp_handles[i]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_dma_mem_free(&pwp->oqp_acchdls[i]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->oqp_handles[i] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < PMCS_NIQ; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->iqp_handles[i]) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_dma_unbind_handle(pwp->iqp_handles[i]) !=
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "Condition check failed at %s():%d",
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh __func__, __LINE__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_dma_free_handle(&pwp->iqp_handles[i]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_dma_mem_free(&pwp->iqp_acchdls[i]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->iqp_handles[i] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_free_dma_chunklist(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Unmap registers and destroy access handles
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->mpi_acc_handle) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_regs_map_free(&pwp->mpi_acc_handle);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->mpi_acc_handle = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->top_acc_handle) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_regs_map_free(&pwp->top_acc_handle);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->top_acc_handle = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->gsm_acc_handle) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_regs_map_free(&pwp->gsm_acc_handle);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->gsm_acc_handle = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->msg_acc_handle) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_regs_map_free(&pwp->msg_acc_handle);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->msg_acc_handle = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->pci_acc_handle) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pci_config_teardown(&pwp->pci_acc_handle);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->pci_acc_handle = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Do memory allocation cleanup.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (pwp->dma_freelist) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dmachunk_t *this = pwp->dma_freelist;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->dma_freelist = this->nxt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_free(this, sizeof (pmcs_dmachunk_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Free pools
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->iocomp_cb_cache) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_cache_destroy(pwp->iocomp_cb_cache);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Free all PHYs (at level > 0), then free the cache
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_free_all_phys(pwp, pwp->root_phys);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->phy_cache) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_cache_destroy(pwp->phy_cache);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Free root PHYs
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->root_phys) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *phyp = pwp->root_phys;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < pwp->nphy; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_destroy(&phyp->phy_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = phyp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_free(pwp->root_phys, pwp->nphy * sizeof (pmcs_phy_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->root_phys = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->nphy = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Free the targets list */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->targets) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_free(pwp->targets,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sizeof (pmcs_xscsi_t *) * pwp->max_dev);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Free work structures
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->work && pwp->max_cmd) {
978d7443a924cda8208d6a10e72be89383bc7becSrikanth Suravajhala for (i = 0; i < pwp->max_cmd; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcwork_t *pwrk = &pwp->work[i];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_destroy(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_destroy(&pwrk->sleep_cv);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_free(pwp->work, sizeof (pmcwork_t) * pwp->max_cmd);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->work = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->max_cmd = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Do last property and SCSA cleanup
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne if (pwp->smp_tran) {
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne smp_hba_tran_free(pwp->smp_tran);
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne pwp->smp_tran = NULL;
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->tran) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_hba_tran_free(pwp->tran);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->tran = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->reset_notify_listf) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_hba_reset_notify_tear_down(pwp->reset_notify_listf);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->reset_notify_listf = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_prop_remove_all(pwp->dip);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->stuck) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Free register dump area if allocated */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->regdumpp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_free(pwp->regdumpp, PMCS_REG_DUMP_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->regdumpp = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->iqpt && pwp->iqpt->head) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_free(pwp->iqpt->head, PMCS_IQP_TRACE_BUFFER_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->iqpt->head = pwp->iqpt->curpos = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->iqpt) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_free(pwp->iqpt, sizeof (pmcs_iqp_trace_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->iqpt = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne /* Destroy pwp's lock */
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne if (pwp->locks_initted) {
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne mutex_destroy(&pwp->lock);
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne mutex_destroy(&pwp->dma_lock);
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne mutex_destroy(&pwp->axil_lock);
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne mutex_destroy(&pwp->cq_lock);
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne mutex_destroy(&pwp->config_lock);
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne mutex_destroy(&pwp->ict_lock);
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne mutex_destroy(&pwp->wfree_lock);
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne mutex_destroy(&pwp->pfree_lock);
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne mutex_destroy(&pwp->dead_phylist_lock);
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne#ifdef DEBUG
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne mutex_destroy(&pwp->dbglock);
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne#endif
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne cv_destroy(&pwp->config_cv);
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne cv_destroy(&pwp->ict_cv);
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne cv_destroy(&pwp->drain_cv);
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne pwp->locks_initted = 0;
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne }
1b94a41b6ff7cb545cabcda970647c0361ed118aChris Horne
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_free(pmcs_softc_state, ddi_get_instance(pwp->dip));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * quiesce (9E) entry point
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This function is called when the system is single-threaded at high PIL
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * with preemption disabled. Therefore, the function must not block/wait/sleep.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Returns DDI_SUCCESS or DDI_FAILURE.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_quiesce(dev_info_t *dip)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_hba_tran_t *tran;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((tran = ddi_get_driver_private(dip)) == NULL)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* No quiesce necessary on a per-iport basis */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (scsi_hba_iport_unit_address(dip) != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((pwp = TRAN2PMC(tran)) == NULL)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Stop MPI & Reset chip (no need to re-initialize) */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_stop_mpi(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_soft_reset(pwp, B_TRUE);
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pwp->last_reset_reason = PMCS_LAST_RST_QUIESCE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with xp->statlock and PHY lock and scratch acquired.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_add_sata_device(pmcs_hw_t *pwp, pmcs_xscsi_t *xp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ata_identify_t *ati;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int result, i;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint16_t *a;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh union {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t nsa[8];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint16_t nsb[4];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } u;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Safe defaults - use only if this target is brand new (i.e. doesn't
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * already have these settings configured)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->capacity == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->capacity = (uint64_t)-1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->ca = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->qdepth = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->pio = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = xp->phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We only try and issue an IDENTIFY for first level
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * (direct attached) devices. We don't try and
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * set other quirks here (this will happen later,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * if the device is fully configured)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->level) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = pmcs_sata_identify(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ati = pwp->scratch;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh a = &ati->word108;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < 4; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh u.nsb[i] = ddi_swap16(*a++);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Check the returned data for being a valid (NAA=5) WWN.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If so, use that and override the SAS address we were
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * given at Link Up time.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((u.nsa[0] >> 4) == 5) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(pptr->sas_address, u.nsa, 8);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: %s has SAS ADDRESS " SAS_ADDR_FMT,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path, SAS_ADDR_PRT(pptr->sas_address));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with PHY lock and target statlock held and scratch acquired
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic boolean_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_add_new_device(pmcs_hw_t *pwp, pmcs_xscsi_t *target)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(target != NULL);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, target, "%s: target = 0x%p",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *) target);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (target->phy->dtype) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SATA:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_add_sata_device(pwp, target) != 0) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, target->phy,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh target, "%s: add_sata_device failed for tgt 0x%p",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *) target);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh target->qdepth = maxqdepth;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case EXPANDER:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh target->qdepth = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh target->new = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh target->assigned = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh target->dev_state = PMCS_DEVICE_STATE_OPERATIONAL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh target->dtype = target->phy->dtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Set the PHY's config stop time to 0. This is one of the final
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * stops along the config path, so we're indicating that we
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * successfully configured the PHY.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh target->phy->config_stop = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_worker(void *arg)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = arg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ulong_t work_flags;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DTRACE_PROBE2(pmcs__worker, ulong_t, pwp->work_flags, boolean_t,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->config_changed);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->state != STATE_RUNNING) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh work_flags = atomic_swap_ulong(&pwp->work_flags, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister if (work_flags & PMCS_WORK_FLAG_DUMP_REGS) {
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister mutex_enter(&pwp->lock);
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister pmcs_register_dump_int(pwp);
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister mutex_exit(&pwp->lock);
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister }
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (work_flags & PMCS_WORK_FLAG_SAS_HW_ACK) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_ack_events(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (work_flags & PMCS_WORK_FLAG_SPINUP_RELEASE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_spinup_release(pwp, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (work_flags & PMCS_WORK_FLAG_SSP_EVT_RECOVERY) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_ssp_event_recovery(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (work_flags & PMCS_WORK_FLAG_DS_ERR_RECOVERY) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dev_state_recovery(pwp, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana if (work_flags & PMCS_WORK_FLAG_DEREGISTER_DEV) {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pmcs_deregister_device_work(pwp, NULL);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana }
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (work_flags & PMCS_WORK_FLAG_DISCOVER) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_discover(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (work_flags & PMCS_WORK_FLAG_ABORT_HANDLE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_abort_handler(pwp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (work_flags & PMCS_WORK_FLAG_SATA_RUN) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_sata_work(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (work_flags & PMCS_WORK_FLAG_RUN_QUEUES) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_scsa_wq_run(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_CQ_RUN(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (work_flags & PMCS_WORK_FLAG_ADD_DMA_CHUNKS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_add_more_chunks(pwp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptob(1) * PMCS_ADDTL_CHUNK_PAGES)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_ADD_DMA_CHUNKS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_add_more_chunks(pmcs_hw_t *pwp, unsigned long nsize)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dmachunk_t *dc;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh unsigned long dl;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_chunk_t *pchunk = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->cip_dma_attr.dma_attr_align = sizeof (uint32_t);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pchunk = kmem_zalloc(sizeof (pmcs_chunk_t), KM_SLEEP);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pchunk == NULL) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Not enough memory for DMA chunks");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_dma_setup(pwp, &pwp->cip_dma_attr, &pchunk->acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pchunk->dma_handle, nsize, (caddr_t *)&pchunk->addrp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pchunk->dma_addr) == B_FALSE) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "Failed to setup DMA for chunks");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_free(pchunk, sizeof (pmcs_chunk_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((pmcs_check_acc_handle(pchunk->acc_handle) != DDI_SUCCESS) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pmcs_check_dma_handle(pchunk->dma_handle) != DDI_SUCCESS)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_fm_service_impact(pwp->dip, DDI_SERVICE_UNAFFECTED);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(pchunk->addrp, nsize);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh dc = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (dl = 0; dl < (nsize / PMCS_SGL_CHUNKSZ); dl++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dmachunk_t *tmp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tmp = kmem_alloc(sizeof (pmcs_dmachunk_t), KM_SLEEP);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tmp->nxt = dc;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh dc = tmp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->dma_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_idma_chunks(pwp, dc, pchunk, nsize);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->nchunks++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->dma_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butlerstatic void
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butlerpmcs_check_forward_progress(pmcs_hw_t *pwp)
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler{
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler pmcwork_t *wrkp;
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler uint32_t *iqp;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler uint32_t cur_iqci;
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler uint32_t cur_work_idx;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler uint32_t cur_msgu_tick;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler uint32_t cur_iop_tick;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler int i;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler mutex_enter(&pwp->lock);
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler if (pwp->state == STATE_IN_RESET) {
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler mutex_exit(&pwp->lock);
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler return;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler }
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler /*
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler * Ensure that inbound work is getting picked up. First, check to
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler * see if new work has been posted. If it has, ensure that the
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler * work is moving forward by checking the consumer index and the
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler * last_htag for the work being processed against what we saw last
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler * time. Note: we use the work structure's 'last_htag' because at
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler * any given moment it could be freed back, thus clearing 'htag'
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler * and setting 'last_htag' (see pmcs_pwork).
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler */
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler for (i = 0; i < PMCS_NIQ; i++) {
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler cur_iqci = pmcs_rd_iqci(pwp, i);
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler iqp = &pwp->iqp[i][cur_iqci * (PMCS_QENTRY_SIZE >> 2)];
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler cur_work_idx = PMCS_TAG_INDEX(LE_32(*(iqp+1)));
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler wrkp = &pwp->work[cur_work_idx];
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler if (cur_iqci == pwp->shadow_iqpi[i]) {
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pwp->last_iqci[i] = cur_iqci;
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler pwp->last_htag[i] = wrkp->last_htag;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler continue;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler }
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler if ((cur_iqci == pwp->last_iqci[i]) &&
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler (wrkp->last_htag == pwp->last_htag[i])) {
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler "Inbound Queue stall detected, issuing reset");
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler goto hot_reset;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler }
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pwp->last_iqci[i] = cur_iqci;
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler pwp->last_htag[i] = wrkp->last_htag;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler }
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler /*
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler * Check heartbeat on both the MSGU and IOP. It is unlikely that
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler * we'd ever fail here, as the inbound queue monitoring code above
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler * would detect a stall due to either of these elements being
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler * stalled, but we might as well keep an eye on them.
d78a6b7e13de1e122f6c7e0d539522698d83ec22Jesse Butler */
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler cur_msgu_tick = pmcs_rd_gst_tbl(pwp, PMCS_GST_MSGU_TICK);
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler if (cur_msgu_tick == pwp->last_msgu_tick) {
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler "Stall detected on MSGU, issuing reset");
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler goto hot_reset;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler }
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pwp->last_msgu_tick = cur_msgu_tick;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler cur_iop_tick = pmcs_rd_gst_tbl(pwp, PMCS_GST_IOP_TICK);
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler if (cur_iop_tick == pwp->last_iop_tick) {
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL,
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler "Stall detected on IOP, issuing reset");
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler goto hot_reset;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler }
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pwp->last_iop_tick = cur_iop_tick;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler mutex_exit(&pwp->lock);
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler return;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butlerhot_reset:
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pwp->state = STATE_DEAD;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler /*
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler * We've detected a stall. Attempt to recover service via hot
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler * reset. In case of failure, pmcs_hot_reset() will handle the
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler * failure and issue any required FM notifications.
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler * See pmcs_subr.c for more details.
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler */
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler if (pmcs_hot_reset(pwp)) {
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler "%s: hot reset failure", __func__);
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler } else {
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler "%s: hot reset complete", __func__);
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pwp->last_reset_reason = PMCS_LAST_RST_STALL;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler }
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler mutex_exit(&pwp->lock);
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_check_commands(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_cmd_t *sp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh size_t amt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char path[32];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcwork_t *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *target;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *phyp;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana int rval;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (pwrk = pwp->work; pwrk < &pwp->work[pwp->max_cmd]; pwrk++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the command isn't active, we can't be timing it still.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Active means the tag is not free and the state is "on chip".
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!PMCS_COMMAND_ACTIVE(pwrk)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * No timer active for this command.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk->timer == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Knock off bits for the time interval.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk->timer >= US2WT(PMCS_WATCH_INTERVAL)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->timer -= US2WT(PMCS_WATCH_INTERVAL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->timer = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk->timer > 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The command has now officially timed out.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Get the path for it. If it doesn't have
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * a phy pointer any more, it's really dead
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * and can just be put back on the free list.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * There should *not* be any commands associated
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * with it any more.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk->phy == NULL) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "dead command with gone phy being recycled");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pwrk->xp == NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh amt = sizeof (path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh amt = min(sizeof (pwrk->phy->path), amt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(path, pwrk->phy->path, amt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If this is a non-SCSA command, stop here. Eventually
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * we might do something with non-SCSA commands here-
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * but so far their timeout mechanisms are handled in
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the WAIT_FOR macro.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk->xp == NULL) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: non-SCSA cmd tag 0x%x timed out",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh path, pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sp = pwrk->arg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(sp != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Mark it as timed out.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CMD2PKT(sp)->pkt_reason = CMD_TIMEOUT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CMD2PKT(sp)->pkt_statistics |= STAT_TIMEOUT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#ifdef DEBUG
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, pwrk->phy, pwrk->xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: SCSA cmd tag 0x%x timed out (state %x) onwire=%d",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh path, pwrk->htag, pwrk->state, pwrk->onwire);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#else
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, pwrk->phy, pwrk->xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: SCSA cmd tag 0x%x timed out (state %x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh path, pwrk->htag, pwrk->state);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#endif
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Mark the work structure as timed out.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_TIMED_OUT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = pwrk->phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh target = pwrk->xp;
3be32c0f0acac4f6258b029f1a27a16a7ec65bb0Jesse Butler ASSERT(target != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&target->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * No point attempting recovery if the device is gone
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (target->dev_gone) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&target->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, target,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: tgt(0x%p) is gone. Returning CMD_DEV_GONE "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "for htag 0x%08x", __func__,
145e0143b4896d03ce53b1af6787afa1a7e73959dh (void *)target, pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!PMCS_COMMAND_DONE(pwrk)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Complete this command here */
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, target,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: Completing cmd (htag 0x%08x) "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "anyway", __func__, pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->dead = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CMD2PKT(sp)->pkt_reason = CMD_DEV_GONE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CMD2PKT(sp)->pkt_state = STATE_GOT_BUS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_complete_work_impl(pwp, pwrk, NULL, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana mutex_exit(&target->statlock);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana rval = pmcs_abort(pwp, phyp, pwrk->htag, 0, 1);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana if (rval) {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, target,
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana "%s: Bad status (%d) on abort of HTAG 0x%08x",
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana __func__, rval, pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana mutex_enter(&pwrk->lock);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana if (!PMCS_COMMAND_DONE(pwrk)) {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana /* Complete this command here */
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, target,
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana "%s: Completing cmd (htag 0x%08x) "
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana "anyway", __func__, pwrk->htag);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana if (target->dev_gone) {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pwrk->dead = 1;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana CMD2PKT(sp)->pkt_reason = CMD_DEV_GONE;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana CMD2PKT(sp)->pkt_state = STATE_GOT_BUS;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana }
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pmcs_complete_work_impl(pwp, pwrk, NULL, 0);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana } else {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana mutex_exit(&pwrk->lock);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana }
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pmcs_lock_phy(phyp);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana /*
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana * No need to reschedule ABORT if we get any other
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana * status
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana */
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana if (rval == ENOMEM) {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana phyp->abort_sent = 0;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana phyp->abort_pending = 1;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Run any completions that may have been queued up.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_CQ_RUN(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_watchdog(void *arg)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = arg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DTRACE_PROBE2(pmcs__watchdog, ulong_t, pwp->work_flags, boolean_t,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->config_changed);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler /*
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler * Check forward progress on the chip
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler */
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler if (++pwp->watchdog_count == PMCS_FWD_PROG_TRIGGER) {
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pwp->watchdog_count = 0;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pmcs_check_forward_progress(pwp);
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler }
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister /*
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister * Check to see if we need to kick discovery off again
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister */
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister mutex_enter(&pwp->config_lock);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister if (pwp->config_restart &&
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister (ddi_get_lbolt() >= pwp->config_restart_time)) {
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister "%s: Timer expired for re-enumeration: Start discovery",
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister __func__);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pwp->config_restart = B_FALSE;
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister }
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister mutex_exit(&pwp->config_lock);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->state != STATE_RUNNING) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (atomic_cas_ulong(&pwp->work_flags, 0, 0) != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_taskq_dispatch(pwp->tq, pmcs_worker, pwp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_NOSLEEP) != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Could not dispatch to worker thread");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->wdhandle = timeout(pmcs_watchdog, pwp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usectohz(PMCS_WATCH_INTERVAL));
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_check_commands(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_handle_dead_phys(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_remove_ihandlers(pmcs_hw_t *pwp, int icnt)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int i, r, rslt = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < icnt; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh r = ddi_intr_remove_handler(pwp->ih_table[i]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (r == DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: unable to remove interrupt handler %d", __func__, i);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rslt = -1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (rslt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_disable_intrs(pmcs_hw_t *pwp, int icnt)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->intr_cap & DDI_INTR_FLAG_BLOCK) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int r = ddi_intr_block_disable(&pwp->ih_table[0],
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->intr_cnt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (r != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "unable to disable interrupt block");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int i;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < icnt; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_intr_disable(pwp->ih_table[i]) == DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "unable to disable interrupt %d", i);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_free_intrs(pmcs_hw_t *pwp, int icnt)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int i;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < icnt; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_intr_free(pwp->ih_table[i]) == DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "unable to free interrupt %d", i);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_free(pwp->ih_table, pwp->ih_table_size);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->ih_table_size = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Try to set up interrupts of type "type" with a minimum number of interrupts
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * of "min".
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_setup_intr_impl(pmcs_hw_t *pwp, int type, int min)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int rval, avail, count, actual, max;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = ddi_intr_get_nintrs(pwp->dip, type, &count);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((rval != DDI_SUCCESS) || (count < min)) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: get_nintrs failed; type: %d rc: %d count: %d min: %d",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, type, rval, count, min);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: nintrs = %d for type: %d", __func__, count, type);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = ddi_intr_get_navail(pwp->dip, type, &avail);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((rval != DDI_SUCCESS) || (avail < min)) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: get_navail failed; type: %d rc: %d avail: %d min: %d",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, type, rval, avail, min);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: navail = %d for type: %d", __func__, avail, type);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->ih_table_size = avail * sizeof (ddi_intr_handle_t);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->ih_table = kmem_alloc(pwp->ih_table_size, KM_SLEEP);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (type) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case DDI_INTR_TYPE_MSIX:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->int_type = PMCS_INT_MSIX;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh max = PMCS_MAX_MSIX;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case DDI_INTR_TYPE_MSI:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->int_type = PMCS_INT_MSI;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh max = PMCS_MAX_MSI;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case DDI_INTR_TYPE_FIXED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->int_type = PMCS_INT_FIXED;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh max = PMCS_MAX_FIXED;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = ddi_intr_alloc(pwp->dip, pwp->ih_table, type, 0, max, &actual,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_INTR_ALLOC_NORMAL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rval != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: ddi_intr_alloc failed; type: %d rc: %d",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, type, rval);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_free(pwp->ih_table, pwp->ih_table_size);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->ih_table = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->ih_table_size = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->intr_cnt = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->int_type = PMCS_INT_NONE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->intr_cnt = actual;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Set up interrupts.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We return one of three values:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * 0 - success
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * EAGAIN - failure to set up interrupts
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * EIO - "" + we're now stuck partly enabled
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If EIO is returned, we can't unload the driver.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_setup_intr(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int i, r, itypes, oqv_count;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_intr_handler_t **iv_table;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh size_t iv_table_size;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint_t pri;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_intr_get_supported_types(pwp->dip, &itypes) != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "cannot get interrupt types");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EAGAIN);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (disable_msix) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh itypes &= ~DDI_INTR_TYPE_MSIX;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (disable_msi) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh itypes &= ~DDI_INTR_TYPE_MSI;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We won't know what firmware we're running until we call pmcs_setup,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * and we can't call pmcs_setup until we establish interrupts.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->int_type = PMCS_INT_NONE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We want PMCS_MAX_MSIX vectors for MSI-X. Anything less would be
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * uncivilized.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (itypes & DDI_INTR_TYPE_MSIX) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_setup_intr_impl(pwp, DDI_INTR_TYPE_MSIX, PMCS_MAX_MSIX);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->int_type == PMCS_INT_MSIX) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh itypes = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (itypes & DDI_INTR_TYPE_MSI) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_setup_intr_impl(pwp, DDI_INTR_TYPE_MSI, 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->int_type == PMCS_INT_MSI) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh itypes = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (itypes & DDI_INTR_TYPE_FIXED) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_setup_intr_impl(pwp, DDI_INTR_TYPE_FIXED, 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->int_type == PMCS_INT_FIXED) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh itypes = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->intr_cnt == 0) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "No interrupts available");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EAGAIN);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iv_table_size = sizeof (ddi_intr_handler_t *) * pwp->intr_cnt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iv_table = kmem_alloc(iv_table_size, KM_SLEEP);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Get iblock cookie and add handlers.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (pwp->intr_cnt) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case 1:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iv_table[0] = pmcs_all_intr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case 2:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iv_table[0] = pmcs_iodone_ix;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iv_table[1] = pmcs_nonio_ix;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case 4:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iv_table[PMCS_MSIX_GENERAL] = pmcs_general_ix;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iv_table[PMCS_MSIX_IODONE] = pmcs_iodone_ix;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iv_table[PMCS_MSIX_EVENTS] = pmcs_event_ix;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iv_table[PMCS_MSIX_FATAL] = pmcs_fatal_ix;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: intr_cnt = %d - unexpected", __func__, pwp->intr_cnt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_free(iv_table, iv_table_size);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EAGAIN);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < pwp->intr_cnt; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh r = ddi_intr_add_handler(pwp->ih_table[i], iv_table[i],
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (caddr_t)pwp, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (r != DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_free(iv_table, iv_table_size);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_remove_ihandlers(pwp, i)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_free_intrs(pwp, i)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->intr_cnt = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EAGAIN);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_free(iv_table, iv_table_size);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_intr_get_cap(pwp->ih_table[0], &pwp->intr_cap) != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "unable to get int capabilities");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_remove_ihandlers(pwp, pwp->intr_cnt)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_free_intrs(pwp, pwp->intr_cnt)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->intr_cnt = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EAGAIN);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->intr_cap & DDI_INTR_FLAG_BLOCK) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh r = ddi_intr_block_enable(&pwp->ih_table[0], pwp->intr_cnt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (r != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "intr blk enable failed");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_remove_ihandlers(pwp, pwp->intr_cnt)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_free_intrs(pwp, pwp->intr_cnt)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->intr_cnt = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EFAULT);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < pwp->intr_cnt; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh r = ddi_intr_enable(pwp->ih_table[i]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (r == DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "unable to enable interrupt %d", i);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_disable_intrs(pwp, i)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_remove_ihandlers(pwp, pwp->intr_cnt)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_free_intrs(pwp, pwp->intr_cnt)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->intr_cnt = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EAGAIN);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Set up locks.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_intr_get_pri(pwp->ih_table[0], &pri) != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "unable to get interrupt priority");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_disable_intrs(pwp, pwp->intr_cnt)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_remove_ihandlers(pwp, pwp->intr_cnt)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_free_intrs(pwp, pwp->intr_cnt)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->intr_cnt = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EAGAIN);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->locks_initted = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->intr_pri = pri;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&pwp->lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&pwp->dma_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&pwp->axil_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&pwp->cq_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&pwp->ict_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&pwp->config_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&pwp->wfree_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&pwp->pfree_lock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&pwp->dead_phylist_lock, NULL, MUTEX_DRIVER,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_INTR_PRI(pri));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#ifdef DEBUG
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&pwp->dbglock, NULL, MUTEX_DRIVER, DDI_INTR_PRI(pri));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#endif
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_init(&pwp->ict_cv, NULL, CV_DRIVER, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_init(&pwp->drain_cv, NULL, CV_DRIVER, NULL);
32b54db7d7ecdb10cc3178edf2c480c6dc5c5559Jesse Butler cv_init(&pwp->config_cv, NULL, CV_DRIVER, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < PMCS_NIQ; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&pwp->iqp_lock[i], NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh MUTEX_DRIVER, DDI_INTR_PRI(pwp->intr_pri));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < pwp->cq_info.cq_threads; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&pwp->cq_info.cq_thr_info[i].cq_thr_lock, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh MUTEX_DRIVER, DDI_INTR_PRI(pwp->intr_pri));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_init(&pwp->cq_info.cq_thr_info[i].cq_cv, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CV_DRIVER, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "%d %s interrup%s configured",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->intr_cnt, (pwp->int_type == PMCS_INT_MSIX)? "MSI-X" :
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ((pwp->int_type == PMCS_INT_MSI)? "MSI" : "INT-X"),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->intr_cnt == 1? "t" : "ts");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Enable Interrupts
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->intr_cnt > PMCS_NOQ) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh oqv_count = pwp->intr_cnt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh oqv_count = PMCS_NOQ;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (pri = 0xffffffff, i = 0; i < oqv_count; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pri ^= (1 << i);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->intr_mask = pri;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_MASK, pwp->intr_mask);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR, 0xffffffff);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_teardown_intr(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->intr_cnt) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_disable_intrs(pwp, pwp->intr_cnt)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_remove_ihandlers(pwp, pwp->intr_cnt)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_free_intrs(pwp, pwp->intr_cnt)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->intr_cnt = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic uint_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_general_ix(caddr_t arg1, caddr_t arg2)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = (pmcs_hw_t *)((void *)arg1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh _NOTE(ARGUNUSED(arg2));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_general_intr(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_INTR_CLAIMED);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic uint_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_event_ix(caddr_t arg1, caddr_t arg2)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = (pmcs_hw_t *)((void *)arg1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh _NOTE(ARGUNUSED(arg2));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_event_intr(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_INTR_CLAIMED);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic uint_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_iodone_ix(caddr_t arg1, caddr_t arg2)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh _NOTE(ARGUNUSED(arg2));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = (pmcs_hw_t *)((void *)arg1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * It's possible that if we just turned interrupt coalescing off
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * (and thus, re-enabled auto clear for interrupts on the I/O outbound
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * queue) that there was an interrupt already pending. We use
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * io_intr_coal.int_cleared to ensure that we still drop in here and
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * clear the appropriate interrupt bit one last time.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->ict_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->io_intr_coal.timer_on ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pwp->io_intr_coal.int_cleared == B_FALSE)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (1 << PMCS_OQ_IODONE));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->io_intr_coal.int_cleared = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->ict_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_iodone_intr(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_INTR_CLAIMED);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic uint_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_fatal_ix(caddr_t arg1, caddr_t arg2)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = (pmcs_hw_t *)((void *)arg1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh _NOTE(ARGUNUSED(arg2));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_fatal_handler(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_INTR_CLAIMED);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic uint_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_nonio_ix(caddr_t arg1, caddr_t arg2)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh _NOTE(ARGUNUSED(arg2));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = (void *)arg1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t obdb = pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Check for Fatal Interrupts
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (obdb & (1 << PMCS_FATAL_INTERRUPT)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_fatal_handler(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_INTR_CLAIMED);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (obdb & (1 << PMCS_OQ_GENERAL)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (1 << PMCS_OQ_GENERAL));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_general_intr(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_event_intr(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_INTR_CLAIMED);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic uint_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_all_intr(caddr_t arg1, caddr_t arg2)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh _NOTE(ARGUNUSED(arg2));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = (void *) arg1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t obdb;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int handled = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh obdb = pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Check for Fatal Interrupts
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (obdb & (1 << PMCS_FATAL_INTERRUPT)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_fatal_handler(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_INTR_CLAIMED);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Check for Outbound Queue service needed
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (obdb & (1 << PMCS_OQ_IODONE)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (1 << PMCS_OQ_IODONE));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh obdb ^= (1 << PMCS_OQ_IODONE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh handled++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_iodone_intr(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (obdb & (1 << PMCS_OQ_GENERAL)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (1 << PMCS_OQ_GENERAL));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh obdb ^= (1 << PMCS_OQ_GENERAL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh handled++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_general_intr(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (obdb & (1 << PMCS_OQ_EVENTS)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (1 << PMCS_OQ_EVENTS));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh obdb ^= (1 << PMCS_OQ_EVENTS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh handled++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_event_intr(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (obdb) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "interrupt bits not handled (0x%x)", obdb);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR, obdb);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh handled++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->int_type == PMCS_INT_MSI) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh handled++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (handled? DDI_INTR_CLAIMED : DDI_INTR_UNCLAIMED);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_fatal_handler(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL, "Fatal Interrupt caught");
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->state = STATE_DEAD;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler /*
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler * Attempt a hot reset. In case of failure, pmcs_hot_reset() will
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler * handle the failure and issue any required FM notifications.
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler * See pmcs_subr.c for more details.
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler */
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler if (pmcs_hot_reset(pwp)) {
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler "%s: hot reset failure", __func__);
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler } else {
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pmcs_prt(pwp, PMCS_PRT_ERR, NULL, NULL,
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler "%s: hot reset complete", __func__);
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pwp->last_reset_reason = PMCS_LAST_RST_FATAL_ERROR;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler }
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with PHY lock and target statlock held and scratch acquired.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhboolean_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_assign_device(pmcs_hw_t *pwp, pmcs_xscsi_t *tgt)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr = tgt->phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (pptr->dtype) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case EXPANDER:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SATA:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->ca = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, tgt,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Target %p has PHY %p with invalid dtype",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)tgt, (void *)pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->new = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->dev_gone = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->recover_wait = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, tgt,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: config %s vtgt %u for " SAS_ADDR_FMT, __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->path, tgt->target_num, SAS_ADDR_PRT(pptr->sas_address));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_add_new_device(pwp, tgt) != B_TRUE) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, tgt,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Failed for vtgt %u / WWN " SAS_ADDR_FMT, __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->target_num, SAS_ADDR_PRT(pptr->sas_address));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_destroy(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_destroy(&tgt->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_destroy(&tgt->aqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with softstate lock held
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_remove_device(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *xp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh unsigned int vtgt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&pwp->lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (vtgt = 0; vtgt < pwp->max_dev; vtgt++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp = pwp->targets[vtgt];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->phy == pptr) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->new) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->new = 0;
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "cancel config of vtgt %u", vtgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler pmcs_clear_xp(pwp, xp);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, xp,
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler "Removed tgt 0x%p vtgt %u",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)xp, vtgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdhpmcs_prt_impl(pmcs_hw_t *pwp, pmcs_prt_level_t level,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_phy_t *phyp, pmcs_xscsi_t *target, const char *fmt, ...)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh va_list ap;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int written = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char *ptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t elem_size = PMCS_TBUF_ELEM_SIZE - 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh boolean_t system_log;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int system_log_level;
1f81b46471e38fdeb9ab74c25510b2f903f8af12David Hollister hrtime_t hrtimestamp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (level) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_PRT_DEBUG_DEVEL:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_PRT_DEBUG_DEV_STATE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_PRT_DEBUG_PHY_LOCKING:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_PRT_DEBUG_SCSI_STATUS:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_PRT_DEBUG_UNDERFLOW:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_PRT_DEBUG_CONFIG:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_PRT_DEBUG_IPORT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_PRT_DEBUG_MAP:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_PRT_DEBUG3:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_PRT_DEBUG2:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_PRT_DEBUG1:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_PRT_DEBUG:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh system_log = B_FALSE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_PRT_INFO:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh system_log = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh system_log_level = CE_CONT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_PRT_WARN:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh system_log = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh system_log_level = CE_NOTE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_PRT_ERR:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh system_log = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh system_log_level = CE_WARN;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pmcs_trace_lock);
1f81b46471e38fdeb9ab74c25510b2f903f8af12David Hollister hrtimestamp = gethrtime();
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh gethrestime(&pmcs_tbuf_ptr->timestamp);
1f81b46471e38fdeb9ab74c25510b2f903f8af12David Hollister
1f81b46471e38fdeb9ab74c25510b2f903f8af12David Hollister if (pwp->fw_timestamp != 0) {
1f81b46471e38fdeb9ab74c25510b2f903f8af12David Hollister /* Calculate the approximate firmware time stamp... */
1f81b46471e38fdeb9ab74c25510b2f903f8af12David Hollister pmcs_tbuf_ptr->fw_timestamp = pwp->fw_timestamp +
1f81b46471e38fdeb9ab74c25510b2f903f8af12David Hollister ((hrtimestamp - pwp->hrtimestamp) / PMCS_FWLOG_TIMER_DIV);
1f81b46471e38fdeb9ab74c25510b2f903f8af12David Hollister } else {
1f81b46471e38fdeb9ab74c25510b2f903f8af12David Hollister pmcs_tbuf_ptr->fw_timestamp = 0;
1f81b46471e38fdeb9ab74c25510b2f903f8af12David Hollister }
1f81b46471e38fdeb9ab74c25510b2f903f8af12David Hollister
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr = pmcs_tbuf_ptr->buf;
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh /*
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh * Store the pertinent PHY and target information if there is any
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh */
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh if (target == NULL) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_tbuf_ptr->target_num = PMCS_INVALID_TARGET_NUM;
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_tbuf_ptr->target_ua[0] = '\0';
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh } else {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_tbuf_ptr->target_num = target->target_num;
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh (void) strncpy(pmcs_tbuf_ptr->target_ua, target->ua,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh PMCS_TBUF_UA_MAX_SIZE);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh }
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh if (phyp == NULL) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh (void) memset(pmcs_tbuf_ptr->phy_sas_address, 0, 8);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_tbuf_ptr->phy_path[0] = '\0';
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_tbuf_ptr->phy_dtype = NOTHING;
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh } else {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh (void) memcpy(pmcs_tbuf_ptr->phy_sas_address,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh phyp->sas_address, 8);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh (void) strncpy(pmcs_tbuf_ptr->phy_path, phyp->path, 32);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_tbuf_ptr->phy_dtype = phyp->dtype;
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh }
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh written += snprintf(ptr, elem_size, "pmcs%d:%d: ",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_get_instance(pwp->dip), level);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr += strlen(ptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh va_start(ap, fmt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh written += vsnprintf(ptr, elem_size - written, fmt, ap);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh va_end(ap);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (written > elem_size - 1) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Indicate truncation */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_tbuf_ptr->buf[elem_size - 1] = '+';
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (++pmcs_tbuf_idx == pmcs_tbuf_num_elems) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_tbuf_ptr = pmcs_tbuf;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_tbuf_wrap = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_tbuf_idx = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ++pmcs_tbuf_ptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pmcs_trace_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * When pmcs_force_syslog in non-zero, everything goes also
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * to syslog, at CE_CONT level.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_force_syslog) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh system_log = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh system_log_level = CE_CONT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Anything that comes in with PMCS_PRT_INFO, WARN, or ERR also
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * goes to syslog.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (system_log) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char local[196];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (system_log_level) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case CE_CONT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(local, sizeof (local), "%sINFO: ",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_console ? "" : "?");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case CE_NOTE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case CE_WARN:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh local[0] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr = local;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr += strlen(local);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(ptr, (sizeof (local)) -
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ((size_t)ptr - (size_t)local), "pmcs%d: ",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_get_instance(pwp->dip));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr += strlen(ptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh va_start(ap, fmt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) vsnprintf(ptr,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (sizeof (local)) - ((size_t)ptr - (size_t)local), fmt, ap);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh va_end(ap);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (level == CE_CONT) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) strlcat(local, "\n", sizeof (local));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cmn_err(system_log_level, local);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * pmcs_acquire_scratch
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If "wait" is true, the caller will wait until it can acquire the scratch.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This implies the caller needs to be in a context where spinning for an
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * indeterminate amount of time is acceptable.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_acquire_scratch(pmcs_hw_t *pwp, boolean_t wait)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int rval;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!wait) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (atomic_swap_8(&pwp->scratch_locked, 1));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Caller will wait for scratch.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while ((rval = atomic_swap_8(&pwp->scratch_locked, 1)) != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(100);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (rval);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_release_scratch(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->scratch_locked = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala/* Called with iport_lock and phy lock held */
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhalavoid
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhalapmcs_create_one_phy_stats(pmcs_iport_t *iport, pmcs_phy_t *phyp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sas_phy_stats_t *ps;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int ndata;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char ks_name[KSTAT_STRLEN];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala ASSERT(mutex_owned(&iport->lock));
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala pwp = iport->pwp;
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala ASSERT(pwp != NULL);
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala ASSERT(mutex_owned(&phyp->phy_lock));
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala if (phyp->phy_stats != NULL) {
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala /*
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala * Delete existing kstats with name containing
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala * old iport instance# and allow creation of
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala * new kstats with new iport instance# in the name.
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala */
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala kstat_delete(phyp->phy_stats);
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala }
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala ndata = (sizeof (sas_phy_stats_t)/sizeof (kstat_named_t));
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala (void) snprintf(ks_name, sizeof (ks_name),
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala "%s.%llx.%d.%d", ddi_driver_name(iport->dip),
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala (longlong_t)pwp->sas_wwns[0],
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala ddi_get_instance(iport->dip), phyp->phynum);
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala phyp->phy_stats = kstat_create("pmcs",
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala ddi_get_instance(iport->dip), ks_name, KSTAT_SAS_PHY_CLASS,
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala KSTAT_TYPE_NAMED, ndata, 0);
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala if (phyp->phy_stats == NULL) {
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, NULL,
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala "%s: Failed to create %s kstats for PHY(0x%p) at %s",
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala __func__, ks_name, (void *)phyp, phyp->path);
978d7443a924cda8208d6a10e72be89383bc7becSrikanth Suravajhala return;
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala }
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala ps = (sas_phy_stats_t *)phyp->phy_stats->ks_data;
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala kstat_named_init(&ps->seconds_since_last_reset,
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala "SecondsSinceLastReset", KSTAT_DATA_ULONGLONG);
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala kstat_named_init(&ps->tx_frames,
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala "TxFrames", KSTAT_DATA_ULONGLONG);
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala kstat_named_init(&ps->rx_frames,
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala "RxFrames", KSTAT_DATA_ULONGLONG);
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala kstat_named_init(&ps->tx_words,
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala "TxWords", KSTAT_DATA_ULONGLONG);
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala kstat_named_init(&ps->rx_words,
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala "RxWords", KSTAT_DATA_ULONGLONG);
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala kstat_named_init(&ps->invalid_dword_count,
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala "InvalidDwordCount", KSTAT_DATA_ULONGLONG);
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala kstat_named_init(&ps->running_disparity_error_count,
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala "RunningDisparityErrorCount", KSTAT_DATA_ULONGLONG);
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala kstat_named_init(&ps->loss_of_dword_sync_count,
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala "LossofDwordSyncCount", KSTAT_DATA_ULONGLONG);
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala kstat_named_init(&ps->phy_reset_problem_count,
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala "PhyResetProblemCount", KSTAT_DATA_ULONGLONG);
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala phyp->phy_stats->ks_private = phyp;
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala phyp->phy_stats->ks_update = pmcs_update_phy_stats;
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala kstat_install(phyp->phy_stats);
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala}
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhalastatic void
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhalapmcs_create_all_phy_stats(pmcs_iport_t *iport)
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala{
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala pmcs_hw_t *pwp;
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala pmcs_phy_t *phyp;
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(iport != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp = iport->pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pwp != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (phyp = list_head(&iport->phys);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp != NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = list_next(&iport->phys, phyp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala mutex_enter(&phyp->phy_lock);
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala pmcs_create_one_phy_stats(iport, phyp);
35dae2328064ca9e149cf5d3a7ba1688ed4629b6Srikanth Suravajhala mutex_exit(&phyp->phy_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_update_phy_stats(kstat_t *ks, int rw)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int val, ret = DDI_FAILURE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr = (pmcs_phy_t *)ks->ks_private;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = pptr->pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sas_phy_stats_t *ps = ks->ks_data;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh _NOTE(ARGUNUSED(rw));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT((pptr != NULL) && (pwp != NULL));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We just want to lock against other invocations of kstat;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * we don't need to pmcs_lock_phy() for this.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pptr->phy_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Get Stats from Chip */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh val = pmcs_get_diag_report(pwp, PMCS_INVALID_DWORD_CNT, pptr->phynum);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (val == DDI_FAILURE)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto fail;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ps->invalid_dword_count.value.ull = (unsigned long long)val;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh val = pmcs_get_diag_report(pwp, PMCS_DISPARITY_ERR_CNT, pptr->phynum);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (val == DDI_FAILURE)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto fail;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ps->running_disparity_error_count.value.ull = (unsigned long long)val;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh val = pmcs_get_diag_report(pwp, PMCS_LOST_DWORD_SYNC_CNT, pptr->phynum);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (val == DDI_FAILURE)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto fail;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ps->loss_of_dword_sync_count.value.ull = (unsigned long long)val;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh val = pmcs_get_diag_report(pwp, PMCS_RESET_FAILED_CNT, pptr->phynum);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (val == DDI_FAILURE)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto fail;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ps->phy_reset_problem_count.value.ull = (unsigned long long)val;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ret = DDI_SUCCESS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhfail:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pptr->phy_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ret);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*ARGSUSED*/
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * as the driver can always deal with an error in any dma or
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * access handle, we can just return the fme_status value.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pci_ereport_post(dip, err, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (err->fme_status);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_fm_init(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_iblock_cookie_t fm_ibc;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Only register with IO Fault Services if we have some capability */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->fm_capabilities) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Adjust access and dma attributes for FMA */
837c1ac4e72b7d86278cca88b1075af557f7d161Stephen Hanson pwp->reg_acc_attr.devacc_attr_access = DDI_FLAGERR_ACC;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->iqp_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->oqp_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->cip_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->fwlog_dma_attr.dma_attr_flags |= DDI_DMA_FLAGERR;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Register capabilities with IO Fault Services.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_fm_init(pwp->dip, &pwp->fm_capabilities, &fm_ibc);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Initialize pci ereport capabilities if ereport
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * capable (should always be.)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (DDI_FM_EREPORT_CAP(pwp->fm_capabilities) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_FM_ERRCB_CAP(pwp->fm_capabilities)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pci_ereport_setup(pwp->dip);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Register error callback if error callback capable.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (DDI_FM_ERRCB_CAP(pwp->fm_capabilities)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_fm_handler_register(pwp->dip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_fm_error_cb, (void *) pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_fm_fini(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Only unregister FMA capabilities if registered */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->fm_capabilities) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Un-register error callback if error callback capable.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (DDI_FM_ERRCB_CAP(pwp->fm_capabilities)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_fm_handler_unregister(pwp->dip);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Release any resources allocated by pci_ereport_setup()
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (DDI_FM_EREPORT_CAP(pwp->fm_capabilities) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_FM_ERRCB_CAP(pwp->fm_capabilities)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pci_ereport_teardown(pwp->dip);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Unregister from IO Fault Services */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_fm_fini(pwp->dip);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Adjust access and dma attributes for FMA */
837c1ac4e72b7d86278cca88b1075af557f7d161Stephen Hanson pwp->reg_acc_attr.devacc_attr_access = DDI_DEFAULT_ACC;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->iqp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->oqp_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->cip_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->fwlog_dma_attr.dma_attr_flags &= ~DDI_DMA_FLAGERR;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic boolean_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_fabricate_wwid(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char *cp, c;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint64_t adr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int i;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cp = &c;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) ddi_strtoul(hw_serial, &cp, 10, (unsigned long *)&adr);
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (adr == 0) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: No serial number available to fabricate WWN",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__);
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler adr = (uint64_t)gethrtime();
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh adr <<= 8;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh adr |= ((uint64_t)ddi_get_instance(pwp->dip) << 52);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh adr |= (5ULL << 60);
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < PMCS_MAX_PORTS; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->sas_wwns[i] = adr + i;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}