pmcs_subr.c revision b18a19c275d2531444fcd2f66664cbe3c6897f6a
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
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Use is subject to license terms.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This file contains various support routines.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#include <sys/scsi/adapters/pmcs/pmcs.h>
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Local static data
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int tgtmap_usec = MICROSEC;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * SAS Topology Configuration
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void pmcs_new_tport(pmcs_hw_t *, pmcs_phy_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void pmcs_configure_expander(pmcs_hw_t *, pmcs_phy_t *, pmcs_iport_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic boolean_t pmcs_check_expanders(pmcs_hw_t *, pmcs_phy_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void pmcs_check_expander(pmcs_hw_t *, pmcs_phy_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void pmcs_clear_expander(pmcs_hw_t *, pmcs_phy_t *, int);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_expander_get_nphy(pmcs_hw_t *, pmcs_phy_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_expander_content_discover(pmcs_hw_t *, pmcs_phy_t *,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_smp_function_result(pmcs_hw_t *, smp_response_frame_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic boolean_t pmcs_validate_devid(pmcs_phy_t *, pmcs_phy_t *, uint32_t);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void pmcs_clear_phys(pmcs_hw_t *, pmcs_phy_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_configure_new_devices(pmcs_hw_t *, pmcs_phy_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic boolean_t pmcs_report_observations(pmcs_hw_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic boolean_t pmcs_report_iport_observations(pmcs_hw_t *, pmcs_iport_t *,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic pmcs_phy_t *pmcs_find_phy_needing_work(pmcs_hw_t *, pmcs_phy_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_kill_devices(pmcs_hw_t *, pmcs_phy_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void pmcs_lock_phy_impl(pmcs_phy_t *, int);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void pmcs_unlock_phy_impl(pmcs_phy_t *, int);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic pmcs_phy_t *pmcs_clone_phy(pmcs_phy_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic boolean_t pmcs_configure_phy(pmcs_hw_t *, pmcs_phy_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void pmcs_reap_dead_phy(pmcs_phy_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic pmcs_iport_t *pmcs_get_iport_by_ua(pmcs_hw_t *, char *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic boolean_t pmcs_phy_target_match(pmcs_phy_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void pmcs_handle_ds_recovery_error(pmcs_phy_t *phyp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *tgt, pmcs_hw_t *pwp, const char *func_name, int line,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char *reason_string);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Often used strings
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhconst char pmcs_nowrk[] = "%s: unable to get work structure";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhconst char pmcs_nomsg[] = "%s: unable to get Inbound Message entry";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhconst char pmcs_timeo[] = "!%s: command timed out";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhextern const ddi_dma_attr_t pmcs_dattr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Some Initial setup steps.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_setup(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t barval = pwp->mpibar;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t i, scratch, regbar, regoff, barbar, baroff;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t new_ioq_depth, ferr = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Check current state. If we're not at READY state,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * we can't go further.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scratch = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((scratch & PMCS_MSGU_AAP_STATE_MASK) == PMCS_MSGU_AAP_STATE_ERROR) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: AAP Error State (0x%x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1) &
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_MSGU_AAP_ERROR_MASK);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_fm_ereport(pwp, DDI_FM_DEVICE_INVAL_STATE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_fm_service_impact(pwp->dip, DDI_SERVICE_LOST);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((scratch & PMCS_MSGU_AAP_STATE_MASK) != PMCS_MSGU_AAP_STATE_READY) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: AAP unit not ready (state 0x%x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, scratch & PMCS_MSGU_AAP_STATE_MASK);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_fm_ereport(pwp, DDI_FM_DEVICE_INVAL_STATE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_fm_service_impact(pwp->dip, DDI_SERVICE_LOST);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Read the offset from the Message Unit scratchpad 0 register.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This allows us to read the MPI Configuration table.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Check its signature for validity.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh baroff = barval;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh barbar = barval >> PMCS_MSGU_MPI_BAR_SHIFT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh baroff &= PMCS_MSGU_MPI_OFFSET_MASK;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh regoff = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh regbar = regoff >> PMCS_MSGU_MPI_BAR_SHIFT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh regoff &= PMCS_MSGU_MPI_OFFSET_MASK;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (regoff > baroff) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: bad MPI Table Length "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "(register offset=0x%08x, passed offset=0x%08x)", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh regoff, baroff);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (regbar != barbar) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: bad MPI BAR (register "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "BAROFF=0x%08x, passed BAROFF=0x%08x)", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh regbar, barbar);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->mpi_offset = regoff;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_AS) != PMCS_SIGNATURE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Bad MPI Configuration Table Signature 0x%x", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rd_mpi_tbl(pwp, PMCS_MPI_AS));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IR) != PMCS_MPI_REVISION1) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Bad MPI Configuration Revision 0x%x", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IR));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Generate offsets for the General System, Inbound Queue Configuration
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * and Outbound Queue configuration tables. This way the macros to
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * access those tables will work correctly.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->mpi_gst_offset =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->mpi_offset + pmcs_rd_mpi_tbl(pwp, PMCS_MPI_GSTO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->mpi_iqc_offset =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->mpi_offset + pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IQCTO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->mpi_oqc_offset =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->mpi_offset + pmcs_rd_mpi_tbl(pwp, PMCS_MPI_OQCTO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->fw = pmcs_rd_mpi_tbl(pwp, PMCS_MPI_FW);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->max_cmd = pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MOIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->max_dev = pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO0) >> 16;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->max_iq = PMCS_MNIQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->max_oq = PMCS_MNOQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->nphy = PMCS_NPHY(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->max_iq <= PMCS_NIQ) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: not enough Inbound Queues "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "supported (need %d, max_oq=%d)", __func__, pwp->max_iq,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_NIQ);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->max_oq <= PMCS_NOQ) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: not enough Outbound Queues "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "supported (need %d, max_oq=%d)", __func__, pwp->max_oq,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_NOQ);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->nphy == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: zero phys reported",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (PMCS_HPIQ(pmcs_rd_mpi_tbl(pwp, PMCS_MPI_INFO1))) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->hipri_queue = (1 << PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < pwp->nphy; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_MPI_EVQSET(pwp, PMCS_OQ_EVENTS, i);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_MPI_NCQSET(pwp, PMCS_OQ_EVENTS, i);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_mpi_tbl(pwp, PMCS_MPI_INFO2,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (PMCS_OQ_EVENTS << GENERAL_EVENT_OQ_SHIFT) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (PMCS_OQ_EVENTS << DEVICE_HANDLE_REMOVED_SHIFT));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Verify that ioq_depth is valid (> 0 and not so high that it
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * would cause us to overrun the chip with commands).
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->ioq_depth == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: I/O queue depth set to 0. Setting to %d",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, PMCS_NQENTRY);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->ioq_depth = PMCS_NQENTRY;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->ioq_depth < PMCS_MIN_NQENTRY) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: I/O queue depth set too low (%d). Setting to %d",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pwp->ioq_depth, PMCS_MIN_NQENTRY);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->ioq_depth = PMCS_MIN_NQENTRY;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->ioq_depth > (pwp->max_cmd / (PMCS_IO_IQ_MASK + 1))) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh new_ioq_depth = pwp->max_cmd / (PMCS_IO_IQ_MASK + 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: I/O queue depth set too high (%d). Setting to %d",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pwp->ioq_depth, new_ioq_depth);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->ioq_depth = new_ioq_depth;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Allocate consistent memory for OQs and IQs.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->iqp_dma_attr = pwp->oqp_dma_attr = pmcs_dattr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->iqp_dma_attr.dma_attr_align =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->oqp_dma_attr.dma_attr_align = PMCS_QENTRY_SIZE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The Rev C chip has the ability to do PIO to or from consistent
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * memory anywhere in a 64 bit address space, but the firmware is
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * not presently set up to do so.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->iqp_dma_attr.dma_attr_addr_hi =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->oqp_dma_attr.dma_attr_addr_hi = 0x000000FFFFFFFFFFull;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < PMCS_NIQ; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_dma_setup(pwp, &pwp->iqp_dma_attr,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->iqp_acchdls[i],
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->iqp_handles[i], PMCS_QENTRY_SIZE * pwp->ioq_depth,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (caddr_t *)&pwp->iqp[i], &pwp->iqaddr[i]) == B_FALSE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Failed to setup DMA for iqp[%d]", i);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(pwp->iqp[i], PMCS_QENTRY_SIZE * pwp->ioq_depth);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < PMCS_NOQ; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_dma_setup(pwp, &pwp->oqp_dma_attr,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->oqp_acchdls[i],
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->oqp_handles[i], PMCS_QENTRY_SIZE * pwp->ioq_depth,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (caddr_t *)&pwp->oqp[i], &pwp->oqaddr[i]) == B_FALSE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Failed to setup DMA for oqp[%d]", i);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(pwp->oqp[i], PMCS_QENTRY_SIZE * pwp->ioq_depth);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Install the IQ and OQ addresses (and null out the rest).
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < pwp->max_iq; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->iqpi_offset[i] = pmcs_rd_iqc_tbl(pwp, PMCS_IQPIOFFX(i));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (i < PMCS_NIQ) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (i != PMCS_IQ_OTHER) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_iqc_tbl(pwp, PMCS_IQC_PARMX(i),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->ioq_depth | (PMCS_QENTRY_SIZE << 16));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_iqc_tbl(pwp, PMCS_IQC_PARMX(i),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (1 << 30) | pwp->ioq_depth |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (PMCS_QENTRY_SIZE << 16));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_iqc_tbl(pwp, PMCS_IQBAHX(i),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DWORD1(pwp->iqaddr[i]));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_iqc_tbl(pwp, PMCS_IQBALX(i),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DWORD0(pwp->iqaddr[i]));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_iqc_tbl(pwp, PMCS_IQCIBAHX(i),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DWORD1(pwp->ciaddr+IQ_OFFSET(i)));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_iqc_tbl(pwp, PMCS_IQCIBALX(i),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DWORD0(pwp->ciaddr+IQ_OFFSET(i)));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_iqc_tbl(pwp, PMCS_IQC_PARMX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_iqc_tbl(pwp, PMCS_IQBAHX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_iqc_tbl(pwp, PMCS_IQBALX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_iqc_tbl(pwp, PMCS_IQCIBAHX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_iqc_tbl(pwp, PMCS_IQCIBALX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < pwp->max_oq; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->oqci_offset[i] = pmcs_rd_oqc_tbl(pwp, PMCS_OQCIOFFX(i));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (i < PMCS_NOQ) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqc_tbl(pwp, PMCS_OQC_PARMX(i), pwp->ioq_depth |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (PMCS_QENTRY_SIZE << 16) | OQIEX);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqc_tbl(pwp, PMCS_OQBAHX(i),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DWORD1(pwp->oqaddr[i]));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqc_tbl(pwp, PMCS_OQBALX(i),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DWORD0(pwp->oqaddr[i]));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqc_tbl(pwp, PMCS_OQPIBAHX(i),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DWORD1(pwp->ciaddr+OQ_OFFSET(i)));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqc_tbl(pwp, PMCS_OQPIBALX(i),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DWORD0(pwp->ciaddr+OQ_OFFSET(i)));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqc_tbl(pwp, PMCS_OQIPARM(i),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->oqvec[i] << 24);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqc_tbl(pwp, PMCS_OQDICX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqc_tbl(pwp, PMCS_OQC_PARMX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqc_tbl(pwp, PMCS_OQBAHX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqc_tbl(pwp, PMCS_OQBALX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqc_tbl(pwp, PMCS_OQPIBAHX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqc_tbl(pwp, PMCS_OQPIBALX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqc_tbl(pwp, PMCS_OQIPARM(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqc_tbl(pwp, PMCS_OQDICX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Set up logging, if defined.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->fwlog) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint64_t logdma = pwp->fwaddr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_mpi_tbl(pwp, PMCS_MPI_MELBAH, DWORD1(logdma));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_mpi_tbl(pwp, PMCS_MPI_MELBAL, DWORD0(logdma));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_mpi_tbl(pwp, PMCS_MPI_MELBS, PMCS_FWLOG_SIZE >> 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_mpi_tbl(pwp, PMCS_MPI_MELSEV, pwp->fwlog);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh logdma += (PMCS_FWLOG_SIZE >> 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_mpi_tbl(pwp, PMCS_MPI_IELBAH, DWORD1(logdma));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_mpi_tbl(pwp, PMCS_MPI_IELBAL, DWORD0(logdma));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_mpi_tbl(pwp, PMCS_MPI_IELBS, PMCS_FWLOG_SIZE >> 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_mpi_tbl(pwp, PMCS_MPI_IELSEV, pwp->fwlog);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Interrupt vectors, outbound queues, and odb_auto_clear
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * MSI/MSI-X:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we got 4 interrupt vectors, we'll assign one to each outbound
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * queue as well as the fatal interrupt, and auto clear can be set
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * for each.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we only got 2 vectors, one will be used for I/O completions
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * and the other for the other two vectors. In this case, auto_
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * clear can only be set for I/Os, which is fine. The fatal
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * interrupt will be mapped to the PMCS_FATAL_INTERRUPT bit, which
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * is not an interrupt vector.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * MSI/MSI-X/INT-X:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we only got 1 interrupt vector, auto_clear must be set to 0,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * and again the fatal interrupt will be mapped to the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * PMCS_FATAL_INTERRUPT bit (again, not an interrupt vector).
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (pwp->int_type) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_INT_MSIX:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_INT_MSI:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (pwp->intr_cnt) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case 1:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_mpi_tbl(pwp, PMCS_MPI_FERR, PMCS_FERRIE |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (PMCS_FATAL_INTERRUPT << PMCS_FERIV_SHIFT));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->odb_auto_clear = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case 2:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_mpi_tbl(pwp, PMCS_MPI_FERR, PMCS_FERRIE |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (PMCS_FATAL_INTERRUPT << PMCS_FERIV_SHIFT));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->odb_auto_clear = (1 << PMCS_FATAL_INTERRUPT) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (1 << PMCS_MSIX_IODONE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case 4:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_mpi_tbl(pwp, PMCS_MPI_FERR, PMCS_FERRIE |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (PMCS_MSIX_FATAL << PMCS_FERIV_SHIFT));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->odb_auto_clear = (1 << PMCS_MSIX_FATAL) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (1 << PMCS_MSIX_GENERAL) | (1 << PMCS_MSIX_IODONE) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (1 << PMCS_MSIX_EVENTS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_INT_FIXED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_mpi_tbl(pwp, PMCS_MPI_FERR,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_FERRIE | (PMCS_FATAL_INTERRUPT << PMCS_FERIV_SHIFT));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->odb_auto_clear = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Enable Interrupt Reassertion
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Default Delay 1000us
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ferr = pmcs_rd_mpi_tbl(pwp, PMCS_MPI_FERR);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((ferr & PMCS_MPI_IRAE) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ferr &= ~(PMCS_MPI_IRAU | PMCS_MPI_IRAD_MASK);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_mpi_tbl(pwp, PMCS_MPI_FERR, ferr | PMCS_MPI_IRAE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_topunit(pwp, PMCS_OBDB_AUTO_CLR, pwp->odb_auto_clear);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->mpi_table_setup = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Start the Message Passing protocol with the PMC chip.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_start_mpi(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int i;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_msgunit(pwp, PMCS_MSGU_IBDB, PMCS_MSGU_IBDB_MPIINI);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < 1000; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB) &
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_MSGU_IBDB_MPIINI) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(1000);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB) & PMCS_MSGU_IBDB_MPIINI) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(500000);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Check to make sure we got to INIT state.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (PMCS_MPI_S(pmcs_rd_gst_tbl(pwp, PMCS_GST_BASE)) !=
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_MPI_STATE_INIT) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: MPI launch failed (GST 0x%x "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "DBCLR 0x%x)", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rd_gst_tbl(pwp, PMCS_GST_BASE),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB_CLEAR));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Stop the Message Passing protocol with the PMC chip.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_stop_mpi(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int i;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < pwp->max_iq; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_iqc_tbl(pwp, PMCS_IQC_PARMX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_iqc_tbl(pwp, PMCS_IQBAHX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_iqc_tbl(pwp, PMCS_IQBALX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_iqc_tbl(pwp, PMCS_IQCIBAHX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_iqc_tbl(pwp, PMCS_IQCIBALX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < pwp->max_oq; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqc_tbl(pwp, PMCS_OQC_PARMX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqc_tbl(pwp, PMCS_OQBAHX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqc_tbl(pwp, PMCS_OQBALX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqc_tbl(pwp, PMCS_OQPIBAHX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqc_tbl(pwp, PMCS_OQPIBALX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqc_tbl(pwp, PMCS_OQIPARM(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqc_tbl(pwp, PMCS_OQDICX(i), 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_mpi_tbl(pwp, PMCS_MPI_FERR, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_msgunit(pwp, PMCS_MSGU_IBDB, PMCS_MSGU_IBDB_MPICTU);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < 2000; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB) &
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_MSGU_IBDB_MPICTU) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(1000);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_rd_msgunit(pwp, PMCS_MSGU_IBDB) & PMCS_MSGU_IBDB_MPICTU) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: MPI stop failed", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Do a sequence of ECHO messages to test for MPI functionality,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * all inbound and outbound queue functionality and interrupts.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_echo_test(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh echo_test_t fred;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct pmcwork *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t *msg, count;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int iqe = 0, iqo = 0, result, rval = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int iterations;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh hrtime_t echo_start, echo_end, echo_total;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pwp->max_cmd > 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We want iterations to be max_cmd * 3 to ensure that we run the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * echo test enough times to iterate through every inbound queue
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * at least twice.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iterations = pwp->max_cmd * 3;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh echo_total = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh count = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (count < iterations) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nowrk, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = -1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->iqp_lock[iqe]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg = GET_IQ_ENTRY(pwp, iqe);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (msg == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[iqe]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nomsg, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = -1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(msg, PMCS_QENTRY_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (iqe == PMCS_IQ_OTHER) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* This is on the high priority queue */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[0] = LE_32(PMCS_HIPRI(pwp, iqo, PMCIN_ECHO));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[0] = LE_32(PMCS_IOMB_IN_SAS(iqo, PMCIN_ECHO));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fred.signature = 0xdeadbeef;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fred.count = count;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fred.ptr = &count;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(&msg[2], &fred, sizeof (fred));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, iqe);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh echo_start = gethrtime();
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DTRACE_PROBE2(pmcs__echo__test__wait__start,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh hrtime_t, echo_start, uint32_t, pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (++iqe == PMCS_NIQ) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iqe = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (++iqo == PMCS_NOQ) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iqo = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh WAIT_FOR(pwrk, 250, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh echo_end = gethrtime();
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DTRACE_PROBE2(pmcs__echo__test__wait__end,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh hrtime_t, echo_end, int, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh echo_total += (echo_end - echo_start);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: command timed out on echo test #%d",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, count);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = -1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The intr_threshold is adjusted by PMCS_INTR_THRESHOLD in order to
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * remove the overhead of things like the delay in getting signaled
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * for completion.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (echo_total != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->io_intr_coal.intr_latency =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (echo_total / iterations) / 2;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->io_intr_coal.intr_threshold =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_INTR_THRESHOLD(PMCS_QUANTUM_TIME_USECS * 1000 /
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->io_intr_coal.intr_latency);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (rval);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Start the (real) phys
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_start_phy(pmcs_hw_t *pwp, int phynum, int linkmode, int speed)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int result;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t *msg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct pmcwork *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sas_identify_af_t sap;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pwp->root_phys + phynum;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: cannot find port %d",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, phynum);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nowrk, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (msg == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nomsg, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_EVENTS, PMCIN_PHY_START));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[2] = LE_32(linkmode | speed | phynum);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(&sap, sizeof (sap));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sap.device_type = SAS_IF_DTYPE_ENDPOINT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sap.ssp_ini_port = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->separate_ports) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wwn2barray(pwp->sas_wwns[phynum], sap.sas_address);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wwn2barray(pwp->sas_wwns[0], sap.sas_address);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(phynum < SAS2_PHYNUM_MAX);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sap.phy_identifier = phynum & SAS2_PHYNUM_MASK;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(&msg[3], &sap, sizeof (sas_identify_af_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->state.prog_min_rate = (lowbit((ulong_t)speed) - 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->state.prog_max_rate = (highbit((ulong_t)speed) - 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->state.hw_min_rate = PMCS_HW_MIN_LINK_RATE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->state.hw_max_rate = PMCS_HW_MAX_LINK_RATE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh WAIT_FOR(pwrk, 1000, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_timeo, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->phys_started |= (1 << phynum);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_start_phys(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int i;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < pwp->nphy; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((pwp->phyid_block_mask & (1 << i)) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_start_phy(pwp, i,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pwp->phymode << PHY_MODE_SHIFT),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->physpeed << PHY_LINK_SHIFT)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_clear_diag_counters(pwp, i)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: failed to "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "reset counters on PHY (%d)", __func__, i);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with PHY locked
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_reset_phy(pmcs_hw_t *pwp, pmcs_phy_t *pptr, uint8_t type)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t *msg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t iomb[(PMCS_QENTRY_SIZE << 1) >> 2];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh const char *mbar;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t amt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t pdevid;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t stsoff;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t status;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int result, level, phynum;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct pmcwork *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t htag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&pptr->phy_lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(iomb, PMCS_QENTRY_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phynum = pptr->phynum;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh level = pptr->level;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (level > 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pdevid = pptr->parent->device_id;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nowrk, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ENOMEM);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->arg = iomb;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If level > 0, we need to issue an SMP_REQUEST with a PHY_CONTROL
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * function to do either a link reset or hard reset. If level == 0,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * then we do a LOCAL_PHY_CONTROL IOMB to do link/hard reset to the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * root (local) PHY
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (level) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh stsoff = 2;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCIN_SMP_REQUEST));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb[2] = LE_32(pdevid);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb[3] = LE_32(40 << SMP_REQUEST_LENGTH_SHIFT);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Send SMP PHY CONTROL/HARD or LINK RESET
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb[4] = BE_32(0x40910000);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb[5] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (type == PMCS_PHYOP_HARD_RESET) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mbar = "SMP PHY CONTROL/HARD RESET";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb[6] = BE_32((phynum << 24) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (PMCS_PHYOP_HARD_RESET << 16));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mbar = "SMP PHY CONTROL/LINK RESET";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb[6] = BE_32((phynum << 24) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (PMCS_PHYOP_LINK_RESET << 16));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: sending %s to %s for phy 0x%x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, mbar, pptr->parent->path, pptr->phynum);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh amt = 7;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Unlike most other Outbound messages, status for
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * a local phy operation is in DWORD 3.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh stsoff = 3;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCIN_LOCAL_PHY_CONTROL));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (type == PMCS_PHYOP_LINK_RESET) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mbar = "LOCAL PHY LINK RESET";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb[2] = LE_32((PMCS_PHYOP_LINK_RESET << 8) | phynum);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mbar = "LOCAL PHY HARD RESET";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iomb[2] = LE_32((PMCS_PHYOP_HARD_RESET << 8) | phynum);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: sending %s to %s", __func__, mbar, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh amt = 3;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (msg == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nomsg, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ENOMEM);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh COPY_MESSAGE(msg, iomb, amt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh htag = pwrk->htag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh WAIT_FOR(pwrk, 1000, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_timeo, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_abort(pwp, pptr, htag, 0, 0)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Unable to issue SMP abort for htag 0x%08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Issuing SMP ABORT for htag 0x%08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh status = LE_32(iomb[stsoff]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (status != PMCOUT_STATUS_OK) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char buf[32];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh const char *es = pmcs_status_str(status);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (es == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(buf, sizeof (buf), "Status 0x%x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh status);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh es = buf;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: %s action returned %s for %s", __func__, mbar, es,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Stop the (real) phys. No PHY or softstate locks are required as this only
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * happens during detach.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_stop_phy(pmcs_hw_t *pwp, int phynum)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int result;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t *msg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct pmcwork *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pwp->root_phys + phynum;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: unable to find port %d", __func__, phynum);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->phys_started & (1 << phynum)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nowrk, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (msg == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nomsg, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_EVENTS, PMCIN_PHY_STOP));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[2] = LE_32(phynum);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Make this unconfigured now.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh WAIT_FOR(pwrk, 1000, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_timeo, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->phys_started &= ~(1 << phynum);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->configured = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * No locks should be required as this is only called during detach
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_stop_phys(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int i;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < pwp->nphy; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((pwp->phyid_block_mask & (1 << i)) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_stop_phy(pwp, i);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Run SAS_DIAG_EXECUTE with cmd and cmd_desc passed.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * ERR_CNT_RESET: return status of cmd
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * DIAG_REPORT_GET: return value of the counter
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_sas_diag_execute(pmcs_hw_t *pwp, uint32_t cmd, uint32_t cmd_desc,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t phynum)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t htag, *ptr, status, msg[PMCS_MSG_SIZE << 1];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int result;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct pmcwork *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nowrk, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->arg = msg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh htag = pwrk->htag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_EVENTS, PMCIN_SAS_DIAG_EXECUTE));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[1] = LE_32(htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[2] = LE_32((cmd << PMCS_DIAG_CMD_SHIFT) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (cmd_desc << PMCS_DIAG_CMD_DESC_SHIFT) | phynum);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ptr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nomsg, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh COPY_MESSAGE(ptr, msg, 3);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh WAIT_FOR(pwrk, 1000, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_timed_out(pwp, htag, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh status = LE_32(msg[3]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Return for counter reset */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (cmd == PMCS_ERR_CNT_RESET)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (status);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Return for counter value */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (status) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: failed, status (0x%x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, status);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (LE_32(msg[4]));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/* Get the current value of the counter for desc on phynum and return it. */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_get_diag_report(pmcs_hw_t *pwp, uint32_t desc, uint8_t phynum)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (pmcs_sas_diag_execute(pwp, PMCS_DIAG_REPORT_GET, desc, phynum));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/* Clear all of the counters for phynum. Returns the status of the command. */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_clear_diag_counters(pmcs_hw_t *pwp, uint8_t phynum)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t cmd = PMCS_ERR_CNT_RESET;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t cmd_desc;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cmd_desc = PMCS_INVALID_DWORD_CNT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_sas_diag_execute(pwp, cmd, cmd_desc, phynum))
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cmd_desc = PMCS_DISPARITY_ERR_CNT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_sas_diag_execute(pwp, cmd, cmd_desc, phynum))
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cmd_desc = PMCS_LOST_DWORD_SYNC_CNT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_sas_diag_execute(pwp, cmd, cmd_desc, phynum))
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cmd_desc = PMCS_RESET_FAILED_CNT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_sas_diag_execute(pwp, cmd, cmd_desc, phynum))
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Get firmware timestamp
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_get_time_stamp(pmcs_hw_t *pwp, uint64_t *ts)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t htag, *ptr, msg[PMCS_MSG_SIZE << 1];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int result;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct pmcwork *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nowrk, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->arg = msg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh htag = pwrk->htag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_EVENTS, PMCIN_GET_TIME_STAMP));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ptr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nomsg, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh COPY_MESSAGE(ptr, msg, 2);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh WAIT_FOR(pwrk, 1000, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_timed_out(pwp, htag, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *ts = LE_32(msg[2]) | (((uint64_t)LE_32(msg[3])) << 32);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Dump all pertinent registers
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_register_dump(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int i;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t val;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO, "pmcs%d: Register dump start",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_get_instance(pwp->dip));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "OBDB (intr): 0x%08x (mask): 0x%08x (clear): 0x%08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB_MASK),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rd_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO, "SCRATCH0: 0x%08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH0));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO, "SCRATCH1: 0x%08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO, "SCRATCH2: 0x%08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH2));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO, "SCRATCH3: 0x%08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH3));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < PMCS_NIQ; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO, "IQ %d: CI %u PI %u",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh i, pmcs_rd_iqci(pwp, i), pmcs_rd_iqpi(pwp, i));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < PMCS_NOQ; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO, "OQ %d: CI %u PI %u",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh i, pmcs_rd_oqci(pwp, i), pmcs_rd_oqpi(pwp, i));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh val = pmcs_rd_gst_tbl(pwp, PMCS_GST_BASE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "GST TABLE BASE: 0x%08x (STATE=0x%x QF=%d GSTLEN=%d HMI_ERR=0x%x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh val, PMCS_MPI_S(val), PMCS_QF(val), PMCS_GSTLEN(val) * 4,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_HMI_ERR(val));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO, "GST TABLE IQFRZ0: 0x%08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rd_gst_tbl(pwp, PMCS_GST_IQFRZ0));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO, "GST TABLE IQFRZ1: 0x%08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rd_gst_tbl(pwp, PMCS_GST_IQFRZ1));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO, "GST TABLE MSGU TICK: 0x%08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rd_gst_tbl(pwp, PMCS_GST_MSGU_TICK));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO, "GST TABLE IOP TICK: 0x%08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rd_gst_tbl(pwp, PMCS_GST_IOP_TICK));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < pwp->nphy; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t rerrf, pinfo, started = 0, link = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pinfo = pmcs_rd_gst_tbl(pwp, PMCS_GST_PHY_INFO(i));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pinfo & 1) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh started = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh link = pinfo & 2;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rerrf = pmcs_rd_gst_tbl(pwp, PMCS_GST_RERR_INFO(i));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "GST TABLE PHY%d STARTED=%d LINK=%d RERR=0x%08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh i, started, link, rerrf);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO, "pmcs%d: Register dump end",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_get_instance(pwp->dip));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Handle SATA Abort and other error processing
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_abort_handler(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr, *pnext, *pnext_uplevel[PMCS_MAX_XPND];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int r, level = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pwp->root_phys;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (pptr) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * XXX: Need to make sure this doesn't happen
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * XXX: when non-NCQ commands are running.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->need_rl_ext) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pptr->dtype == SATA);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_acquire_scratch(pwp, B_FALSE)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh r = pmcs_sata_abort_ncq(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_release_scratch(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (r == ENOMEM) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (r) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh r = pmcs_reset_phy(pwp, pptr,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_PHYOP_LINK_RESET);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (r == ENOMEM) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* what if other failures happened? */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->abort_pending = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->abort_sent = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->abort_pending == 0 || pptr->abort_sent) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->abort_pending = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_abort(pwp, pptr, pptr->device_id, 1, 1) == ENOMEM) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->abort_pending = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->abort_sent = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhnext_phy:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->children) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pnext = pptr->children;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pnext_uplevel[level++] = pptr->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pnext = pptr->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while ((pnext == NULL) && (level > 0)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pnext = pnext_uplevel[--level];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pnext;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Register a device (get a device handle for it).
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with PHY lock held.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_register_device(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct pmcwork *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int result = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t *msg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t tmp, status;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t iomb[(PMCS_QENTRY_SIZE << 1) >> 2];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (msg == NULL ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr)) == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = ENOMEM;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->arg = iomb;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->dtype = pptr->dtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL, PMCIN_REGISTER_DEVICE));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tmp = PMCS_DEVREG_TLR |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pptr->link_rate << PMCS_DEVREG_LINK_RATE_SHIFT);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (IS_ROOT_PHY(pptr)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[2] = LE_32(pptr->portid |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pptr->phynum << PMCS_PHYID_SHIFT));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[2] = LE_32(pptr->portid);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->dtype == SATA) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (IS_ROOT_PHY(pptr)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tmp |= PMCS_DEVREG_TYPE_SATA_DIRECT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tmp |= PMCS_DEVREG_TYPE_SATA;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tmp |= PMCS_DEVREG_TYPE_SAS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[3] = LE_32(tmp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[4] = LE_32(PMCS_DEVREG_IT_NEXUS_TIMEOUT);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(&msg[5], pptr->sas_address, 8);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CLEAN_MESSAGE(msg, 7);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh WAIT_FOR(pwrk, 250, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_timeo, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = ETIMEDOUT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh status = LE_32(iomb[2]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tmp = LE_32(iomb[3]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (status) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_DEVREG_OK:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_DEVREG_DEVICE_ALREADY_REGISTERED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_DEVREG_PHY_ALREADY_REGISTERED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_validate_devid(pwp->root_phys, pptr, tmp) == B_FALSE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = EEXIST;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (status != PMCS_DEVREG_OK) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tmp == 0xffffffff) { /* F/W bug */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: phy %s already has bogus devid 0x%x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path, tmp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = EIO;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: phy %s already has a device id 0x%x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path, tmp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: status 0x%x when trying to "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "register device %s", __func__, status, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = EIO;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->device_id = tmp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->valid_device_id = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "Phy %s/" SAS_ADDR_FMT
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh " registered with device_id 0x%x (portid %d)", pptr->path,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SAS_ADDR_PRT(pptr->sas_address), tmp, pptr->portid);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhout:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Deregister a device (remove a device handle).
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with PHY locked.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_deregister_device(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct pmcwork *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t msg[PMCS_MSG_SIZE], *ptr, status;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t iomb[(PMCS_QENTRY_SIZE << 1) >> 2];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int result;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->arg = iomb;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->dtype = pptr->dtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ptr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCIN_DEREGISTER_DEVICE_HANDLE));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[2] = LE_32(pptr->device_id);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh COPY_MESSAGE(ptr, msg, 3);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh WAIT_FOR(pwrk, 250, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_timeo, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh status = LE_32(iomb[2]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (status != PMCOUT_STATUS_OK) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: status 0x%x when trying to "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "deregister device %s", __func__, status, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: device %s deregistered",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->valid_device_id = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->device_id = PMCS_INVALID_DEVICE_ID;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Deregister all registered devices.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_deregister_devices(pmcs_hw_t *pwp, pmcs_phy_t *phyp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Start at the maximum level and walk back to level 0. This only
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * gets done during detach after all threads and timers have been
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * destroyed, so there's no need to hold the softstate or PHY lock.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (phyp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp->children) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_deregister_devices(pwp, phyp->children);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp->valid_device_id) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_deregister_device(pwp, phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = phyp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Perform a 'soft' reset on the PMC chip
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_soft_reset(pmcs_hw_t *pwp, boolean_t no_restart)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t s2, sfrbits, gsm, rapchk, wapchk, wdpchk, spc, tsmode;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char *msg = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int i;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Disable interrupts
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_MASK, 0xffffffff);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR, 0xffffffff);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO, "%s", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->locks_initted) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->blocked = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 1
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh s2 = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH2);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((s2 & PMCS_MSGU_HOST_SOFT_RESET_READY) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_gsm_reg(pwp, RB6_ACCESS, RB6_NMI_SIGNATURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_gsm_reg(pwp, RB6_ACCESS, RB6_NMI_SIGNATURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < 100; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh s2 = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH2) &
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_MSGU_HOST_SOFT_RESET_READY;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (s2) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(10000);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh s2 = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH2) &
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_MSGU_HOST_SOFT_RESET_READY;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (s2 == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: PMCS_MSGU_HOST_"
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "SOFT_RESET_READY never came ready", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_register_dump(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1) &
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_MSGU_CPU_SOFT_RESET_READY) == 0 ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH2) &
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_MSGU_CPU_SOFT_RESET_READY) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->state = STATE_DEAD;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->blocked = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->locks_initted) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 2
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_gsm_reg(pwp, NMI_EN_VPE0_IOP, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(10);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_gsm_reg(pwp, NMI_EN_VPE0_AAP1, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(10);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_topunit(pwp, PMCS_EVENT_INT_ENABLE, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(10);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_topunit(pwp, PMCS_EVENT_INT_STAT,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rd_topunit(pwp, PMCS_EVENT_INT_STAT));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(10);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_topunit(pwp, PMCS_ERROR_INT_ENABLE, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(10);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_topunit(pwp, PMCS_ERROR_INT_STAT,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rd_topunit(pwp, PMCS_ERROR_INT_STAT));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(10);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sfrbits = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1) &
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_MSGU_AAP_SFR_PROGRESS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sfrbits ^= PMCS_MSGU_AAP_SFR_PROGRESS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG2, "PMCS_MSGU_HOST_SCRATCH0 %08x -> %08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rd_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH0), HST_SFT_RESET_SIG);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_msgunit(pwp, PMCS_MSGU_HOST_SCRATCH0, HST_SFT_RESET_SIG);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 3
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh gsm = pmcs_rd_gsm_reg(pwp, GSM_CFG_AND_RESET);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG2, "GSM %08x -> %08x", gsm,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh gsm & ~PMCS_SOFT_RESET_BITS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_gsm_reg(pwp, GSM_CFG_AND_RESET, gsm & ~PMCS_SOFT_RESET_BITS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 4
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rapchk = pmcs_rd_gsm_reg(pwp, READ_ADR_PARITY_CHK_EN);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG2, "READ_ADR_PARITY_CHK_EN %08x -> %08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rapchk, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_gsm_reg(pwp, READ_ADR_PARITY_CHK_EN, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh wapchk = pmcs_rd_gsm_reg(pwp, WRITE_ADR_PARITY_CHK_EN);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG2, "WRITE_ADR_PARITY_CHK_EN %08x -> %08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh wapchk, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_gsm_reg(pwp, WRITE_ADR_PARITY_CHK_EN, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh wdpchk = pmcs_rd_gsm_reg(pwp, WRITE_DATA_PARITY_CHK_EN);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG2, "WRITE_DATA_PARITY_CHK_EN %08x -> %08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh wdpchk, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_gsm_reg(pwp, WRITE_DATA_PARITY_CHK_EN, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 5
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(100);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 5.5 (Temporary workaround for 1.07.xx Beta)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tsmode = pmcs_rd_gsm_reg(pwp, PMCS_GPIO_TRISTATE_MODE_ADDR);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG2, "GPIO TSMODE %08x -> %08x", tsmode,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tsmode & ~(PMCS_GPIO_TSMODE_BIT0|PMCS_GPIO_TSMODE_BIT1));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_gsm_reg(pwp, PMCS_GPIO_TRISTATE_MODE_ADDR,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tsmode & ~(PMCS_GPIO_TSMODE_BIT0|PMCS_GPIO_TSMODE_BIT1));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(10);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 6
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh spc = pmcs_rd_topunit(pwp, PMCS_SPC_RESET);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG2, "SPC_RESET %08x -> %08x", spc,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh spc & ~(PCS_IOP_SS_RSTB|PCS_AAP1_SS_RSTB));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_topunit(pwp, PMCS_SPC_RESET,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh spc & ~(PCS_IOP_SS_RSTB|PCS_AAP1_SS_RSTB));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(10);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 7
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh spc = pmcs_rd_topunit(pwp, PMCS_SPC_RESET);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG2, "SPC_RESET %08x -> %08x", spc,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh spc & ~(BDMA_CORE_RSTB|OSSP_RSTB));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_topunit(pwp, PMCS_SPC_RESET, spc & ~(BDMA_CORE_RSTB|OSSP_RSTB));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 8
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(100);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 9
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh spc = pmcs_rd_topunit(pwp, PMCS_SPC_RESET);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG2, "SPC_RESET %08x -> %08x", spc,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh spc | (BDMA_CORE_RSTB|OSSP_RSTB));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_topunit(pwp, PMCS_SPC_RESET, spc | (BDMA_CORE_RSTB|OSSP_RSTB));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 10
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(100);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 11
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh gsm = pmcs_rd_gsm_reg(pwp, GSM_CFG_AND_RESET);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG2, "GSM %08x -> %08x", gsm,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh gsm | PMCS_SOFT_RESET_BITS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_gsm_reg(pwp, GSM_CFG_AND_RESET, gsm | PMCS_SOFT_RESET_BITS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(10);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 12
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG2, "READ_ADR_PARITY_CHK_EN %08x -> %08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rd_gsm_reg(pwp, READ_ADR_PARITY_CHK_EN), rapchk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_gsm_reg(pwp, READ_ADR_PARITY_CHK_EN, rapchk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(10);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG2, "WRITE_ADR_PARITY_CHK_EN %08x -> %08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rd_gsm_reg(pwp, WRITE_ADR_PARITY_CHK_EN), wapchk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_gsm_reg(pwp, WRITE_ADR_PARITY_CHK_EN, wapchk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(10);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG2, "WRITE_DATA_PARITY_CHK_EN %08x -> %08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rd_gsm_reg(pwp, WRITE_DATA_PARITY_CHK_EN), wapchk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_gsm_reg(pwp, WRITE_DATA_PARITY_CHK_EN, wdpchk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(10);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 13
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh spc = pmcs_rd_topunit(pwp, PMCS_SPC_RESET);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG2, "SPC_RESET %08x -> %08x", spc,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh spc | (PCS_IOP_SS_RSTB|PCS_AAP1_SS_RSTB));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_topunit(pwp, PMCS_SPC_RESET,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh spc | (PCS_IOP_SS_RSTB|PCS_AAP1_SS_RSTB));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 14
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(100);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 15
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (spc = 0, i = 0; i < 1000; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(1000);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh spc = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((spc & PMCS_MSGU_AAP_SFR_PROGRESS) == sfrbits) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((spc & PMCS_MSGU_AAP_SFR_PROGRESS) != sfrbits) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "SFR didn't toggle (sfr 0x%x)", spc);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->state = STATE_DEAD;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->blocked = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->locks_initted) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 16
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_MASK, 0xffffffff);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR, 0xffffffff);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Wait for up to 5 seconds for AAP state to come either ready or error.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < 50; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh spc = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1) &
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_MSGU_AAP_STATE_MASK;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (spc == PMCS_MSGU_AAP_STATE_ERROR ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh spc == PMCS_MSGU_AAP_STATE_READY) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(100000);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh spc = pmcs_rd_msgunit(pwp, PMCS_MSGU_SCRATCH1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((spc & PMCS_MSGU_AAP_STATE_MASK) != PMCS_MSGU_AAP_STATE_READY) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "soft reset failed (state 0x%x)", spc);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->state = STATE_DEAD;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->blocked = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->locks_initted) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->state == STATE_DEAD || pwp->state == STATE_UNPROBING ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->state == STATE_PROBING || pwp->locks_initted == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->blocked = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->locks_initted) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Return at this point if we dont need to startup.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (no_restart) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pwp->locks_initted != 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Clean up various soft state.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(pwp->ports, sizeof (pwp->ports));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_free_all_phys(pwp, pwp->root_phys);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (pptr = pwp->root_phys; pptr; pptr = pptr->sibling) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_clear_phy(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->targets) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < pwp->max_dev; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *xp = pwp->targets[i];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler pmcs_clear_xp(pwp, xp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(pwp->shadow_iqpi, sizeof (pwp->shadow_iqpi));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < PMCS_NIQ; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->iqp[i]) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(pwp->iqp[i], PMCS_QENTRY_SIZE * pwp->ioq_depth);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_iqpi(pwp, i, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_iqci(pwp, i, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < PMCS_NOQ; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->oqp[i]) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(pwp->oqp[i], PMCS_QENTRY_SIZE * pwp->ioq_depth);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqpi(pwp, i, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_oqci(pwp, i, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->fwlogp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(pwp->fwlogp, PMCS_FWLOG_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INIT(&pwp->wf);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(pwp->work, sizeof (pmcwork_t) * pwp->max_cmd);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < pwp->max_cmd - 1; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcwork_t *pwrk = &pwp->work[i];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_TAIL(&pwp->wf, pwrk, next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Clear out any leftover commands sitting in the work list
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < pwp->max_cmd; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcwork_t *pwrk = &pwp->work[i];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk->state == PMCS_WORK_STATE_ONCHIP) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (PMCS_TAG_TYPE(pwrk->htag)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_TAG_TYPE_WAIT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_TAG_TYPE_CBACK:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_TAG_TYPE_NONE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (pwrk->state == PMCS_WORK_STATE_IOCOMPQ) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->dead = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The other states of NIL, READY and INTR
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * should not be visible outside of a lock being held.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Restore Interrupt Mask
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_MASK, pwp->intr_mask);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_msgunit(pwp, PMCS_MSGU_OBDB_CLEAR, 0xffffffff);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->blocked = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->mpi_table_setup = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Set up MPI again.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_setup(pwp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg = "unable to setup MPI tables again";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto fail_restart;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_report_fwversion(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Restart MPI
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_start_mpi(pwp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg = "unable to restart MPI again";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto fail_restart;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->blocked = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Run any completions
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_CQ_RUN(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Delay
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(1000000);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhfail_restart:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->state = STATE_DEAD;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, "%s: Failed: %s", __func__, msg);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Reset a device or a logical unit.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_reset_dev(pmcs_hw_t *pwp, pmcs_phy_t *pptr, uint64_t lun)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int rval = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ENXIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->dtype == SAS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Some devices do not support SAS_I_T_NEXUS_RESET as
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * it is not a mandatory (in SAM4) task management
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * function, while LOGIC_UNIT_RESET is mandatory.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The problem here is that we need to iterate over
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * all known LUNs to emulate the semantics of
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * "RESET_TARGET".
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * XXX: FIX ME
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (lun == (uint64_t)-1) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh lun = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = pmcs_ssp_tmf(pwp, pptr, SAS_LOGICAL_UNIT_RESET, 0, lun,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (pptr->dtype == SATA) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (lun != 0ull) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EINVAL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = pmcs_reset_phy(pwp, pptr, PMCS_PHYOP_LINK_RESET);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: cannot reset a SMP device yet (%s)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EINVAL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Now harvest any commands killed by this action
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * by issuing an ABORT for all commands on this device.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We do this even if the the tmf or reset fails (in case there
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * are any dead commands around to be harvested *anyway*).
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We don't have to await for the abort to complete.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_abort(pwp, pptr, 0, 1, 0)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->abort_pending = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (rval);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with PHY locked.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_get_device_handle(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->valid_device_id == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int result = pmcs_register_device(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we changed while registering, punt
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->changed) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh RESTART_DISCOVERY(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we had a failure to register, check against errors.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * An ENOMEM error means we just retry (temp resource shortage).
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result == ENOMEM) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PHY_CHANGED(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh RESTART_DISCOVERY(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * An ETIMEDOUT error means we retry (if our counter isn't
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * exhausted)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result == ETIMEDOUT) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_get_lbolt() < pptr->config_stop) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PHY_CHANGED(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh RESTART_DISCOVERY(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Retries exhausted for %s, killing",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->config_stop = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_kill_changed(pwp, pptr, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Other errors or no valid device id is fatal, but don't
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * preclude a future action.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result || pptr->valid_device_id == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "%s: %s could not "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "be registered", __func__, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_iport_tgtmap_create(pmcs_iport_t *iport)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (iport == NULL)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(iport->pwp, PMCS_PRT_DEBUG_MAP, "%s", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* create target map */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (scsi_hba_tgtmap_create(iport->dip, SCSI_TM_FULLSET, tgtmap_usec,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 2048, NULL, NULL, NULL, &iport->iss_tgtmap) != DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(iport->pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: failed to create tgtmap", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_iport_tgtmap_destroy(pmcs_iport_t *iport)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(iport && iport->iss_tgtmap);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((iport == NULL) || (iport->iss_tgtmap == NULL))
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(iport->pwp, PMCS_PRT_DEBUG_MAP, "%s", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* destroy target map */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_hba_tgtmap_destroy(iport->iss_tgtmap);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Query the phymap and populate the iport handle passed in.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with iport lock held.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_iport_configure_phys(pmcs_iport_t *iport)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sas_phymap_phys_t *phys;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int phynum;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int inst;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&iport->lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp = iport->pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh inst = ddi_get_instance(iport->dip);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pwp->root_phys != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Query the phymap regarding the phys in this iport and populate
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the iport's phys list. Hereafter this list is maintained via
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * port up and down events in pmcs_intr.c
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(list_is_empty(&iport->phys));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phys = sas_phymap_ua2phys(pwp->hss_phymap, iport->ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while ((phynum = sas_phymap_phys_next(phys)) != -1) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Grab the phy pointer from root_phys */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pwp->root_phys + phynum;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pptr->phynum == phynum);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Set a back pointer in the phy to this iport.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->iport = iport;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If this phy is the primary, set a pointer to it on our
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * iport handle, and set our portid from it.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!pptr->subsidiary) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport->pptr = pptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport->portid = pptr->portid;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Finally, insert the phy into our list
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_add_phy_to_iport(iport, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "%s: found phy %d [0x%p] "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "on iport%d, refcnt(%d)", __func__, phynum,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)pptr, inst, iport->refcnt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sas_phymap_phys_free(phys);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh RESTART_DISCOVERY(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Return the iport that ua is associated with, or NULL. If an iport is
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * returned, it will be held and the caller must release the hold.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic pmcs_iport_t *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_get_iport_by_ua(pmcs_hw_t *pwp, char *ua)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_iport_t *iport = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rw_enter(&pwp->iports_lock, RW_READER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (iport = list_head(&pwp->iports);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport != NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport = list_next(&pwp->iports, iport)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (strcmp(iport->ua, ua) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&iport->refcnt_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport->refcnt++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&iport->refcnt_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rw_exit(&pwp->iports_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Return the iport that pptr is associated with, or NULL.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If an iport is returned, there is a hold that the caller must release.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_iport_t *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_get_iport_by_phy(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_iport_t *iport = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char *ua;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ua = sas_phymap_lookup_ua(pwp->hss_phymap, pwp->sas_wwns[0],
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_barray2wwn(pptr->sas_address));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ua) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport = pmcs_get_iport_by_ua(pwp, ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (iport) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport->ua_state = UA_ACTIVE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "%s: "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "found iport [0x%p] on ua (%s) for phy [0x%p], "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "refcnt (%d)", __func__, (void *)iport, ua,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)pptr, iport->refcnt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_rele_iport(pmcs_iport_t *iport)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Release a refcnt on this iport. If this is the last reference,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * signal the potential waiter in pmcs_iport_unattach().
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(iport->refcnt > 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&iport->refcnt_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport->refcnt--;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&iport->refcnt_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (iport->refcnt == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_signal(&iport->refcnt_cv);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(iport->pwp, PMCS_PRT_DEBUG_CONFIG, "%s: iport [0x%p] "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "refcnt (%d)", __func__, (void *)iport, iport->refcnt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_phymap_activate(void *arg, char *ua, void **privp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh _NOTE(ARGUNUSED(privp));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = arg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_iport_t *iport = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((pwp->state == STATE_UNPROBING) || (pwp->state == STATE_DEAD)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->phymap_active++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (scsi_hba_iportmap_iport_add(pwp->hss_iportmap, ua, NULL) !=
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, "%s: failed to add "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "iport handle on unit address [%s]", __func__, ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, "%s: phymap_active count "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "(%d), added iport handle on unit address [%s]", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->phymap_active, ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Set the HBA softstate as our private data for this unit address */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *privp = (void *)pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We are waiting on attach for this iport node, unless it is still
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * attached. This can happen if a consumer has an outstanding open
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * on our iport node, but the port is down. If this is the case, we
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * need to configure our iport here for reuse.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport = pmcs_get_iport_by_ua(pwp, ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (iport) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_iport_configure_phys(iport) != DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "%s: "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "failed to configure phys on iport [0x%p] at "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "unit address (%s)", __func__, (void *)iport, ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport->ua_state = UA_ACTIVE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_smhba_add_iport_prop(iport, DATA_TYPE_INT32, PMCS_NUM_PHYS,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &iport->nphy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rele_iport(iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_phymap_deactivate(void *arg, char *ua, void *privp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh _NOTE(ARGUNUSED(privp));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = arg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_iport_t *iport;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->phymap_active--;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (scsi_hba_iportmap_iport_remove(pwp->hss_iportmap, ua) !=
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, "%s: failed to remove "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "iport handle on unit address [%s]", __func__, ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP, "%s: phymap_active "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "count (%d), removed iport handle on unit address [%s]",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pwp->phymap_active, ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport = pmcs_get_iport_by_ua(pwp, ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (iport == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "%s: failed lookup of "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "iport handle on unit address (%s)", __func__, ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport->ua_state = UA_INACTIVE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport->portid = PMCS_IPORT_INVALID_PORT_ID;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_remove_phy_from_iport(iport, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rele_iport(iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Top-level discovery function
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_discover(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *root_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DTRACE_PROBE2(pmcs__discover__entry, ulong_t, pwp->work_flags,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh boolean_t, pwp->config_changed);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->state != STATE_RUNNING) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Ensure we have at least one phymap active */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->phymap_active == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: phymap inactive, exiting", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If no iports have attached, but we have PHYs that are up, we
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * are waiting for iport attach to complete. Restart discovery.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rw_enter(&pwp->iports_lock, RW_READER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!pwp->iports_attached) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rw_exit(&pwp->iports_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: no iports attached, retry discovery", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rw_exit(&pwp->iports_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->configuring) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: configuration already in progress", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_acquire_scratch(pwp, B_FALSE)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: cannot allocate scratch", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->configuring = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->config_changed = B_FALSE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "Discovery begin");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The order of the following traversals is important.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The first one checks for changed expanders.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The second one aborts commands for dead devices and deregisters them.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The third one clears the contents of dead expanders from the tree
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The fourth one clears now dead devices in expanders that remain.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * 1. Check expanders marked changed (but not dead) to see if they still
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * have the same number of phys and the same SAS address. Mark them,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * their subsidiary phys (if wide) and their descendents dead if
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * anything has changed. Check the devices they contain to see if
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * *they* have changed. If they've changed from type NOTHING we leave
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * them marked changed to be configured later (picking up a new SAS
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * address and link rate if possible). Otherwise, any change in type,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * SAS address or removal of target role will cause us to mark them
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * (and their descendents) as dead (and cause any pending commands
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * and associated devices to be removed).
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh root_phy = pwp->root_phys;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_check_expanders(pwp, root_phy) == B_TRUE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * 2. Descend the tree looking for dead devices and kill them
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * by aborting all active commands and then deregistering them.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_kill_devices(pwp, root_phy)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * 3. Check for dead expanders and remove their children from the tree.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * By the time we get here, the devices and commands for them have
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * already been terminated and removed.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We do this independent of the configuration count changing so we can
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * free any dead device PHYs that were discovered while checking
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * expanders. We ignore any subsidiary phys as pmcs_clear_expander
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * will take care of those.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * NOTE: pmcs_clear_expander requires softstate lock
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (pptr = pwp->root_phys; pptr; pptr = pptr->sibling) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Call pmcs_clear_expander for every root PHY. It will
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * recurse and determine which (if any) expanders actually
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * need to be cleared.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_clear_expander(pwp, pptr, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * 4. Check for dead devices and nullify them. By the time we get here,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the devices and commands for them have already been terminated
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * and removed. This is different from step 2 in that this just nulls
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * phys that are part of expanders that are still here but used to
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * be something but are no longer something (e.g., after a pulled
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * disk drive). Note that dead expanders had their contained phys
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * removed from the tree- here, the expanders themselves are
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * nullified (unless they were removed by being contained in another
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * expander phy).
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_clear_phys(pwp, root_phy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * 5. Now check for and configure new devices.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_configure_new_devices(pwp, root_phy)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto restart;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhout:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DTRACE_PROBE2(pmcs__discover__exit, ulong_t, pwp->work_flags,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh boolean_t, pwp->config_changed);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "Discovery end");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->config_changed == B_FALSE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Observation is stable, report what we currently see to
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the tgtmaps for delta processing. Start by setting
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * BEGIN on all tgtmaps.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_report_observations(pwp) == B_FALSE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto restart;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If config_changed is TRUE, we need to reschedule
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * discovery now.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Config has changed, will re-run discovery", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_DISCOVER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_release_scratch(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->configuring = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#ifdef DEBUG
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pmcs_find_phy_needing_work(pwp, pwp->root_phys);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!WORK_IS_SCHEDULED(pwp, PMCS_WORK_DISCOVER)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "PHY %s dead=%d changed=%d configured=%d "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "but no work scheduled", pptr->path, pptr->dead,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->changed, pptr->configured);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#endif
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhrestart:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Clean up and restart discovery */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_release_scratch(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->configuring = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh RESTART_DISCOVERY_LOCKED(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Return any PHY that needs to have scheduled work done. The PHY is returned
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * locked.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic pmcs_phy_t *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_find_phy_needing_work(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *cphyp, *pnext;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (pptr) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->changed || (pptr->dead && pptr->valid_device_id)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pnext = pptr->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->children) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cphyp = pptr->children;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cphyp = pmcs_find_phy_needing_work(pwp, cphyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (cphyp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (cphyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pnext;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Report current observations to SCSA.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic boolean_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_report_observations(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_iport_t *iport;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_hba_tgtmap_t *tgtmap;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char *ap;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint64_t wwn;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Observation is stable, report what we currently see to the tgtmaps
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * for delta processing. Start by setting BEGIN on all tgtmaps.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rw_enter(&pwp->iports_lock, RW_READER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (iport = list_head(&pwp->iports); iport != NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport = list_next(&pwp->iports, iport)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Unless we have at least one phy up, skip this iport.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Note we don't need to lock the iport for report_skip
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * since it is only used here. We are doing the skip so that
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the phymap and iportmap stabilization times are honored -
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * giving us the ability to recover port operation within the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * stabilization time without unconfiguring targets using the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * port.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!sas_phymap_uahasphys(pwp->hss_phymap, iport->ua)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport->report_skip = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue; /* skip set_begin */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport->report_skip = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgtmap = iport->iss_tgtmap;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(tgtmap);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (scsi_hba_tgtmap_set_begin(tgtmap) != DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: cannot set_begin tgtmap ", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rw_exit(&pwp->iports_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: set begin on tgtmap [0x%p]", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)tgtmap);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rw_exit(&pwp->iports_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Now, cycle through all levels of all phys and report
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * observations into their respective tgtmaps.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pwp->root_phys;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (pptr) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Skip PHYs that have nothing attached or are dead.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((pptr->dtype == NOTHING) || pptr->dead) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pptr->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->changed) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: oops, PHY %s changed; restart discovery",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Get the iport for this root PHY, then call the helper
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * to report observations for this iport's targets
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport = pmcs_get_iport_by_phy(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (iport == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* No iport for this tgt */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: no iport for this target",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pptr->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!iport->report_skip) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_report_iport_observations(
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp, iport, pptr) == B_FALSE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rele_iport(iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rele_iport(iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pptr->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The observation is complete, end sets. Note we will skip any
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * iports that are active, but have no PHYs in them (i.e. awaiting
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * unconfigure). Set to restart discovery if we find this.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rw_enter(&pwp->iports_lock, RW_READER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (iport = list_head(&pwp->iports);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport != NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport = list_next(&pwp->iports, iport)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (iport->report_skip)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue; /* skip set_end */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgtmap = iport->iss_tgtmap;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(tgtmap);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (scsi_hba_tgtmap_set_end(tgtmap, 0) != DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: cannot set_end tgtmap ", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rw_exit(&pwp->iports_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: set end on tgtmap [0x%p]", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)tgtmap);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Now that discovery is complete, set up the necessary
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * DDI properties on each iport node.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (iport = list_head(&pwp->iports); iport != NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport = list_next(&pwp->iports, iport)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Set up the DDI properties on each phy */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_smhba_set_phy_props(iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Set up the 'attached-port' property on the iport */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ap = kmem_zalloc(PMCS_MAX_UA_SIZE, KM_SLEEP);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = iport->pptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&iport->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This iport is down, but has not been
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * removed from our list (unconfigured).
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Set our value to '0'.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(ap, 1, "%s", "0");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Otherwise, set it to remote phy's wwn */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh wwn = pmcs_barray2wwn(pptr->sas_address);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) scsi_wwn_to_wwnstr(wwn, 1, ap);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ndi_prop_update_string(DDI_DEV_T_NONE, iport->dip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCSI_ADDR_PROP_ATTACHED_PORT, ap) != DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: Failed to "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "set prop ("SCSI_ADDR_PROP_ATTACHED_PORT")",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_free(ap, PMCS_MAX_UA_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rw_exit(&pwp->iports_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Report observations into a particular iport's target map
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with phyp (and all descendents) locked
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic boolean_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_report_iport_observations(pmcs_hw_t *pwp, pmcs_iport_t *iport,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *phyp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *lphyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_hba_tgtmap_t *tgtmap;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_tgtmap_tgt_type_t tgt_type;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char *ua;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint64_t wwn;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgtmap = iport->iss_tgtmap;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(tgtmap);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh lphyp = phyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (lphyp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (lphyp->dtype) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default: /* Skip unknown PHYs. */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* for non-root phys, skip to sibling */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SATA:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt_type = SCSI_TGT_SCSI_DEVICE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case EXPANDER:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt_type = SCSI_TGT_SMP_DEVICE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (lphyp->dead) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh wwn = pmcs_barray2wwn(lphyp->sas_address);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ua = scsi_wwn_to_wwnstr(wwn, 1, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "iport_observation: adding %s on tgtmap [0x%p] phy [0x%p]",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ua, (void *)tgtmap, (void*)lphyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (scsi_hba_tgtmap_set_add(tgtmap, tgt_type, ua, NULL) !=
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_MAP,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: failed to add address %s", __func__, ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_free_wwnstr(ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_free_wwnstr(ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (lphyp->children) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_report_iport_observations(pwp, iport,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh lphyp->children) == B_FALSE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* for non-root phys, report siblings too */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhnext_phy:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (IS_ROOT_PHY(lphyp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh lphyp = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh lphyp = lphyp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Check for and configure new devices.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the changed device is a SATA device, add a SATA device.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the changed device is a SAS device, add a SAS device.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the changed device is an EXPANDER device, do a REPORT
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * GENERAL SMP command to find out the number of contained phys.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * For each number of contained phys, allocate a phy, do a
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * DISCOVERY SMP command to find out what kind of device it
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * is and add it to the linked list of phys on the *next* level.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * NOTE: pptr passed in by the caller will be a root PHY
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_configure_new_devices(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int rval = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_iport_t *iport;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pnext, *orig_pptr = pptr, *root_phy, *pchild;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * First, walk through each PHY at this level
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (pptr) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pnext = pptr->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Set the new dtype if it has changed
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((pptr->pend_dtype != NEW) &&
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pptr->pend_dtype != pptr->dtype)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->dtype = pptr->pend_dtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->changed == 0 || pptr->dead || pptr->configured) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Confirm that this target's iport is configured
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh root_phy = pmcs_get_root_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport = pmcs_get_iport_by_phy(pwp, root_phy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (iport == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* No iport for this tgt, restart */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: iport not yet configured, "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "retry discovery", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pnext = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = -1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (pptr->dtype) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case NOTHING:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->changed = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SATA:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->iport = iport;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_new_tport(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case EXPANDER:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_configure_expander(pwp, pptr, iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rele_iport(iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->config_changed) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pnext = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhnext_phy:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pnext;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rval != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (rval);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Now walk through each PHY again, recalling ourselves if they
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * have children
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = orig_pptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (pptr) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pnext = pptr->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pchild = pptr->children;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pchild) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = pmcs_configure_new_devices(pwp, pchild);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rval != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pnext;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (rval);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Set all phys and descendent phys as changed if changed == B_TRUE, otherwise
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * mark them all as not changed.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with parent PHY locked.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_set_changed(pmcs_hw_t *pwp, pmcs_phy_t *parent, boolean_t changed,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int level)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (level == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (changed) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PHY_CHANGED(pwp, parent);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh parent->changed = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (parent->dtype == EXPANDER && parent->level) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh parent->width = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (parent->children) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_set_changed(pwp, parent->children, changed,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh level + 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = parent;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (pptr) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (changed) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PHY_CHANGED(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->changed = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->dtype == EXPANDER && pptr->level) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->width = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->children) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_set_changed(pwp, pptr->children, changed,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh level + 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pptr->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Take the passed phy mark it and its descendants as dead.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Fire up reconfiguration to abort commands and bury it.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with the parent PHY locked.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_kill_changed(pmcs_hw_t *pwp, pmcs_phy_t *parent, int level)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr = parent;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (pptr) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->link_rate = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->abort_sent = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->abort_pending = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->need_rl_ext = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->dead == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PHY_CHANGED(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh RESTART_DISCOVERY(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->dead = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->children) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_kill_changed(pwp, pptr->children, level + 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Only kill siblings at level > 0
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (level == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pptr->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Go through every PHY and clear any that are dead (unless they're expanders)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_clear_phys(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pnext, *phyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = pptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (phyp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (IS_ROOT_PHY(phyp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((phyp->dtype != EXPANDER) && phyp->dead) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_clear_phy(pwp, phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp->children) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_clear_phys(pwp, phyp->children);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pnext = phyp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (IS_ROOT_PHY(phyp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = pnext;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Clear volatile parts of a phy. Called with PHY locked.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_clear_phy(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "%s: %s", __func__, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&pptr->phy_lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* keep sibling */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* keep children */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* keep parent */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->device_id = PMCS_INVALID_DEVICE_ID;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* keep hw_event_ack */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->ncphy = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* keep phynum */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->width = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->ds_recovery_retries = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* keep dtype */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->config_stop = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->spinup_hold = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->atdt = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* keep portid */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->link_rate = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->valid_device_id = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->abort_sent = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->abort_pending = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->need_rl_ext = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->subsidiary = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->configured = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Only mark dead if it's not a root PHY and its dtype isn't NOTHING */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* XXX: What about directly attached disks? */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!IS_ROOT_PHY(pptr) && (pptr->dtype != NOTHING))
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->dead = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->changed = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* keep SAS address */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* keep path */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* keep ref_count */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Don't clear iport on root PHYs - they are handled in pmcs_intr.c */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!IS_ROOT_PHY(pptr)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->iport = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler /* keep target */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Allocate softstate for this target if there isn't already one. If there
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * is, just redo our internal configuration. If it is actually "new", we'll
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * soon get a tran_tgt_init for it.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with PHY locked.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_new_tport(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "%s: phy 0x%p @ %s", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)pptr, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_configure_phy(pwp, pptr) == B_FALSE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the config failed, mark the PHY as changed.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PHY_CHANGED(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: pmcs_configure_phy failed for phy 0x%p", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Mark PHY as no longer changed */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->changed = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the PHY has no target pointer, see if there's a dead PHY that
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * matches.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->target == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_reap_dead_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Only assign the device if there is a target for this PHY with a
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * matching SAS address. If an iport is disconnected from one piece
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * of storage and connected to another within the iport stabilization
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * time, we can get the PHY/target mismatch situation.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Otherwise, it'll get done in tran_tgt_init.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->target) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pptr->target->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_phy_target_match(pptr) == B_FALSE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pptr->target->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!IS_ROOT_PHY(pptr)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dec_phy_ref_count(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Not assigning existing tgt %p for PHY %p "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "(WWN mismatch)", __func__, (void *)pptr->target,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->target = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!pmcs_assign_device(pwp, pptr->target)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: pmcs_assign_device failed for target 0x%p",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)pptr->target);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pptr->target->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with PHY lock held.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic boolean_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_configure_phy(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char *dtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&pptr->phy_lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Mark this device as no longer changed.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->changed = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we don't have a device handle, get one.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_get_device_handle(pwp, pptr)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->configured = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (pptr->dtype) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh dtype = "SAS";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SATA:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh dtype = "SATA";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case EXPANDER:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh dtype = "SMP";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh dtype = "???";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "config_dev: %s dev %s "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SAS_ADDR_FMT " dev id 0x%x lr 0x%x", dtype, pptr->path,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SAS_ADDR_PRT(pptr->sas_address), pptr->device_id, pptr->link_rate);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with PHY locked
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_configure_expander(pmcs_hw_t *pwp, pmcs_phy_t *pptr, pmcs_iport_t *iport)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *ctmp, *clist = NULL, *cnext;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int result, i, nphy = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh boolean_t root_phy = B_FALSE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 1- clear our "changed" bit. If we need to retry/restart due
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * to resource shortages, we'll set it again. While we're doing
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * configuration, other events may set it again as well. If the PHY
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * is a root PHY and is currently marked as having changed, reset the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * config_stop timer as well.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (IS_ROOT_PHY(pptr) && pptr->changed) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->config_stop = ddi_get_lbolt() +
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usectohz(PMCS_MAX_CONFIG_TIME);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->changed = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 2- make sure we don't overflow
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->level == PMCS_MAX_XPND-1) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_WARN,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: SAS expansion tree too deep", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 3- Check if this expander is part of a wide phy that has
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * already been configured.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This is known by checking this level for another EXPANDER device
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * with the same SAS address and isn't already marked as a subsidiary
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * phy and a parent whose SAS address is the same as our SAS address
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * (if there are parents).
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!IS_ROOT_PHY(pptr)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * No need to lock the parent here because we're in discovery
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * and the only time a PHY's children pointer can change is
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * in discovery; either in pmcs_clear_expander (which has
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * already been called) or here, down below. Plus, trying to
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * grab the parent's lock here can cause deadlock.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = pptr->parent->children;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = pwp->root_phys;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh root_phy = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (ctmp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we've checked all PHYs up to pptr, we stop. Otherwise,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * we'll be checking for a primary PHY with a higher PHY
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * number than pptr, which will never happen. The primary
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * PHY on non-root expanders will ALWAYS be the lowest
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * numbered PHY.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ctmp == pptr) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If pptr and ctmp are root PHYs, just grab the mutex on
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * ctmp. No need to lock the entire tree. If they are not
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * root PHYs, there is no need to lock since a non-root PHY's
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * SAS address and other characteristics can only change in
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * discovery anyway.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (root_phy) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&ctmp->phy_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ctmp->dtype == EXPANDER && ctmp->width &&
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh memcmp(ctmp->sas_address, pptr->sas_address, 8) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int widephy = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If these phys are not root PHYs, compare their SAS
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * addresses too.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!root_phy) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (memcmp(ctmp->parent->sas_address,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->parent->sas_address, 8) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh widephy = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh widephy = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (widephy) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->width++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->subsidiary = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "%s: PHY "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s part of wide PHY %s (now %d wide)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path, ctmp->path,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->width);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (root_phy) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&ctmp->phy_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cnext = ctmp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (root_phy) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&ctmp->phy_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = cnext;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 4- If we don't have a device handle, get one. Since this
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * is the primary PHY, make sure subsidiary is cleared.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->subsidiary = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_get_device_handle(pwp, pptr)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "Config expander %s "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SAS_ADDR_FMT " dev id 0x%x lr 0x%x", pptr->path,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SAS_ADDR_PRT(pptr->sas_address), pptr->device_id, pptr->link_rate);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 5- figure out how many phys are in this expander.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh nphy = pmcs_expander_get_nphy(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (nphy <= 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (nphy == 0 && ddi_get_lbolt() < pptr->config_stop) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PHY_CHANGED(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh RESTART_DISCOVERY(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Retries exhausted for %s, killing", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->config_stop = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_kill_changed(pwp, pptr, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 6- Allocate a list of phys for this expander and figure out
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * what each one is.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < nphy; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = kmem_cache_alloc(pwp->phy_cache, KM_SLEEP);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(ctmp, sizeof (pmcs_phy_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->device_id = PMCS_INVALID_DEVICE_ID;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->sibling = clist;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->pend_dtype = NEW; /* Init pending dtype */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->config_stop = ddi_get_lbolt() +
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usectohz(PMCS_MAX_CONFIG_TIME);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh clist = ctmp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->config_changed) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh RESTART_DISCOVERY_LOCKED(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Clean up the newly allocated PHYs and return
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (clist) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = clist->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_cache_free(pwp->phy_cache, clist);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh clist = ctmp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 7- Now fill in the rest of the static portions of the phy.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0, ctmp = clist; ctmp; ctmp = ctmp->sibling, i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->parent = pptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->pwp = pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->level = pptr->level+1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->portid = pptr->portid;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ctmp->tolerates_sas2) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(i < SAS2_PHYNUM_MAX);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->phynum = i & SAS2_PHYNUM_MASK;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(i < SAS_PHYNUM_MAX);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->phynum = i & SAS_PHYNUM_MASK;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_name(pwp, ctmp, ctmp->path, sizeof (ctmp->path));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(ctmp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 8- Discover things about each phy in the expander.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0, ctmp = clist; ctmp; ctmp = ctmp->sibling, i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = pmcs_expander_content_discover(pwp, pptr, ctmp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result <= 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_get_lbolt() < pptr->config_stop) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PHY_CHANGED(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh RESTART_DISCOVERY(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->config_stop = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Retries exhausted for %s, killing",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_kill_changed(pwp, pptr, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Set pend_dtype to dtype for 1st time initialization */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->pend_dtype = ctmp->dtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 9- Install the new list on the next level. There should be
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * no children pointer on this PHY. If there is, we'd need to know
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * how it happened (The expander suddenly got more PHYs?).
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pptr->children == NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->children != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: Already child PHYs attached "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh " to PHY %s: This should never happen", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->children = clist;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh clist = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->ncphy = nphy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->configured = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We only set width if we're greater than level 0.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->level) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->width = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Now tell the rest of the world about us, as an SMP node.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->iport = iport;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_new_tport(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhout:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (clist) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = clist->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(clist);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_cache_free(pwp->phy_cache, clist);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh clist = ctmp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * 2. Check expanders marked changed (but not dead) to see if they still have
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the same number of phys and the same SAS address. Mark them, their subsidiary
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * phys (if wide) and their descendents dead if anything has changed. Check the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the devices they contain to see if *they* have changed. If they've changed
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * from type NOTHING we leave them marked changed to be configured later
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * (picking up a new SAS address and link rate if possible). Otherwise, any
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * change in type, SAS address or removal of target role will cause us to
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * mark them (and their descendents) as dead and cause any pending commands
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * and associated devices to be removed.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with PHY (pptr) locked.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_check_expander(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int nphy, result;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *ctmp, *local, *local_list = NULL, *local_tail = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh boolean_t kill_changed, changed;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: check %s", __func__, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 1: Mark phy as not changed. We will mark it changed if we need
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * to retry.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->changed = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Reset the config_stop time. Although we're not actually configuring
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * anything here, we do want some indication of when to give up trying
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * if we can't communicate with the expander.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->config_stop = ddi_get_lbolt() +
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usectohz(PMCS_MAX_CONFIG_TIME);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 2: Figure out how many phys are in this expander. If
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * pmcs_expander_get_nphy returns 0 we ran out of resources,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * so reschedule and try later. If it returns another error,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * just return.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh nphy = pmcs_expander_get_nphy(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (nphy <= 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((nphy == 0) && (ddi_get_lbolt() < pptr->config_stop)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PHY_CHANGED(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh RESTART_DISCOVERY(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->config_stop = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Retries exhausted for %s, killing", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_kill_changed(pwp, pptr, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 3: If the number of phys don't agree, kill the old sub-tree.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (nphy != pptr->ncphy) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: number of contained phys for %s changed from %d to %d",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path, pptr->ncphy, nphy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Force a rescan of this expander after dead contents
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * are cleared and removed.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_kill_changed(pwp, pptr, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 4: if we're at the bottom of the stack, we're done
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * (we can't have any levels below us)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->level == PMCS_MAX_XPND-1) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 5: Discover things about each phy in this expander. We do
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * this by walking the current list of contained phys and doing a
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * content discovery for it to a local phy.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = pptr->children;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(ctmp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ctmp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: No children attached to expander @ %s?", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (ctmp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Allocate a local PHY to contain the proposed new contents
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * and link it to the rest of the local PHYs so that they
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * can all be freed later.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh local = pmcs_clone_phy(ctmp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (local_list == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh local_list = local;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh local_tail = local;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh local_tail->sibling = local;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh local_tail = local;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Need to lock the local PHY since pmcs_expander_content_
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * discovery may call pmcs_clear_phy on it, which expects
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the PHY to be locked.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(local);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = pmcs_expander_content_discover(pwp, pptr, local);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(local);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result <= 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_get_lbolt() < pptr->config_stop) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PHY_CHANGED(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh RESTART_DISCOVERY(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->config_stop = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Retries exhausted for %s, killing",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_kill_changed(pwp, pptr, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Release all the local PHYs that we allocated.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_free_phys(pwp, local_list);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = ctmp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 6: Compare the local PHY's contents to our current PHY. If
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * there are changes, take the appropriate action.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This is done in two steps (step 5 above, and 6 here) so that if we
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * have to bail during this process (e.g. pmcs_expander_content_discover
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * fails), we haven't actually changed the state of any of the real
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * PHYs. Next time we come through here, we'll be starting over from
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * scratch. This keeps us from marking a changed PHY as no longer
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * changed, but then having to bail only to come back next time and
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * think that the PHY hadn't changed. If this were to happen, we
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * would fail to properly configure the device behind this PHY.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh local = local_list;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = pptr->children;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (ctmp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh changed = B_FALSE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kill_changed = B_FALSE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We set local to local_list prior to this loop so that we
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * can simply walk the local_list while we walk this list. The
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * two lists should be completely in sync.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Clear the changed flag here.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->changed = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ctmp->dtype != local->dtype) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ctmp->dtype != NOTHING) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "%s: %s "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "type changed from %s to %s (killing)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, ctmp->path, PHY_TYPE(ctmp),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PHY_TYPE(local));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Force a rescan of this expander after dead
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * contents are cleared and removed.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh changed = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kill_changed = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh changed = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: %s type changed from NOTHING to %s",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, ctmp->path, PHY_TYPE(local));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (ctmp->atdt != local->atdt) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "%s: %s attached "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "device type changed from %d to %d (killing)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, ctmp->path, ctmp->atdt, local->atdt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Force a rescan of this expander after dead
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * contents are cleared and removed.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh changed = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (local->atdt == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kill_changed = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (ctmp->link_rate != local->link_rate) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO, "%s: %s changed speed from"
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh " %s to %s", __func__, ctmp->path,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_get_rate(ctmp->link_rate),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_get_rate(local->link_rate));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* If the speed changed from invalid, force rescan */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!PMCS_VALID_LINK_RATE(ctmp->link_rate)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh changed = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh RESTART_DISCOVERY(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Just update to the new link rate */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->link_rate = local->link_rate;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!PMCS_VALID_LINK_RATE(local->link_rate)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kill_changed = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (memcmp(ctmp->sas_address, local->sas_address,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sizeof (ctmp->sas_address)) != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "%s: SASAddr "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "for %s changed from " SAS_ADDR_FMT " to "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SAS_ADDR_FMT " (kill old tree)", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->path, SAS_ADDR_PRT(ctmp->sas_address),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SAS_ADDR_PRT(local->sas_address));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Force a rescan of this expander after dead
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * contents are cleared and removed.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh changed = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: %s looks the same (type %s)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, ctmp->path, PHY_TYPE(ctmp));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If EXPANDER, still mark it changed so we
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * re-evaluate its contents. If it's not an expander,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * but it hasn't been configured, also mark it as
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * changed so that it will undergo configuration.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ctmp->dtype == EXPANDER) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh changed = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if ((ctmp->dtype != NOTHING) &&
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh !ctmp->configured) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->changed = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* It simply hasn't changed */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->changed = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the PHY changed, call pmcs_kill_changed if indicated,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * update its contents to reflect its current state and mark it
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * as changed.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (changed) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * pmcs_kill_changed will mark the PHY as changed, so
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * only do PHY_CHANGED if we did not do kill_changed.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (kill_changed) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_kill_changed(pwp, ctmp, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we're not killing the device, it's not
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * dead. Mark the PHY as changed.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PHY_CHANGED(pwp, ctmp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ctmp->dead) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Unmarking PHY %s dead, "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "restarting discovery",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, ctmp->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->dead = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh RESTART_DISCOVERY(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the dtype of this PHY is now NOTHING, mark it as
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * unconfigured. Set pend_dtype to what the new dtype
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * is. It'll get updated at the end of the discovery
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * process.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (local->dtype == NOTHING) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(ctmp->sas_address,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sizeof (local->sas_address));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->atdt = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->link_rate = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->pend_dtype = NOTHING;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->configured = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(ctmp->sas_address,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh local->sas_address,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sizeof (local->sas_address));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->atdt = local->atdt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->link_rate = local->link_rate;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->pend_dtype = local->dtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh local = local->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = ctmp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we got to here, that means we were able to see all the PHYs
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * and we can now update all of the real PHYs with the information
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * we got on the local PHYs. Once that's done, free all the local
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * PHYs.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_free_phys(pwp, local_list);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Top level routine to check expanders. We call pmcs_check_expander for
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * each expander. Since we're not doing any configuration right now, it
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * doesn't matter if this is breadth-first.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic boolean_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_check_expanders(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *phyp, *pnext, *pchild;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh boolean_t config_changed = B_FALSE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "%s: %s", __func__, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Check each expander at this level
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = pptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (phyp && !config_changed) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((phyp->dtype == EXPANDER) && phyp->changed &&
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh !phyp->dead && !phyp->subsidiary &&
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp->configured) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_check_expander(pwp, phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pnext = phyp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh config_changed = pwp->config_changed;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = pnext;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (config_changed) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (config_changed);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Now check the children
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = pptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (phyp && !config_changed) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pnext = phyp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pchild = phyp->children;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pchild) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_check_expanders(pwp, pchild);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh config_changed = pwp->config_changed;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = pnext;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We're done
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (config_changed);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with softstate and PHY locked
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_clear_expander(pmcs_hw_t *pwp, pmcs_phy_t *pptr, int level)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *ctmp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&pwp->lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&pptr->phy_lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pptr->level < PMCS_MAX_XPND - 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "%s: checking %s", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = pptr->children;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (ctmp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the expander is dead, mark its children dead
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->dead) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->dead = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ctmp->dtype == EXPANDER) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_clear_expander(pwp, ctmp, level + 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = ctmp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If this expander is not dead, we're done here.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!pptr->dead) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Now snip out the list of children below us and release them
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = pptr->children;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (ctmp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *nxt = ctmp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: dead PHY 0x%p (%s) (ref_count %d)", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)ctmp, ctmp->path, ctmp->ref_count);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Put this PHY on the dead PHY list for the watchdog to
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * clean up after any outstanding work has completed.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->dead_phylist_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->dead_next = pwp->dead_phys;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->dead_phys = ctmp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->dead_phylist_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(ctmp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = nxt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->children = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Clear subsidiary phys as well. Getting the parent's PHY lock
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * is only necessary if level == 0 since otherwise the parent is
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * already locked.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!IS_ROOT_PHY(pptr)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (level == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pptr->parent->phy_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = pptr->parent->children;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (level == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pptr->parent->phy_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = pwp->root_phys;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (ctmp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ctmp == pptr) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = ctmp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We only need to lock subsidiary PHYs on the level 0
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * expander. Any children of that expander, subsidiaries or
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * not, will already be locked.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (level == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(ctmp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ctmp->dtype != EXPANDER || ctmp->subsidiary == 0 ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh memcmp(ctmp->sas_address, pptr->sas_address,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sizeof (ctmp->sas_address)) != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (level == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(ctmp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = ctmp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "%s: subsidiary %s",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, ctmp->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_clear_phy(pwp, ctmp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (level == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(ctmp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = ctmp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_clear_phy(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with PHY locked and with scratch acquired. We return 0 if
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * we fail to allocate resources or notice that the configuration
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * count changed while we were running the command. We return
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * less than zero if we had an I/O error or received an unsupported
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * configuration. Otherwise we return the number of phys in the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * expander.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#define DFM(m, y) if (m == NULL) m = y
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_expander_get_nphy(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct pmcwork *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char buf[64];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh const uint_t rdoff = 0x100; /* returned data offset */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh smp_response_frame_t *srf;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh smp_report_general_resp_t *srgr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t msg[PMCS_MSG_SIZE], *ptr, htag, status, ival;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int result;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ival = 0x40001100;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhagain:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memset(pwp->scratch, 0x77, PMCS_SCRATCH_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->arg = pwp->scratch;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->dtype = pptr->dtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ptr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG2, "%s: GET_IQ_ENTRY failed",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL, PMCIN_SMP_REQUEST));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[2] = LE_32(pptr->device_id);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[3] = LE_32((4 << SMP_REQUEST_LENGTH_SHIFT) | SMP_INDIRECT_RESPONSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Send SMP REPORT GENERAL (of either SAS1.1 or SAS2 flavors).
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[4] = BE_32(ival);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[5] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[6] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[7] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[8] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[9] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[10] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[11] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[12] = LE_32(DWORD0(pwp->scratch_dma+rdoff));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[13] = LE_32(DWORD1(pwp->scratch_dma+rdoff));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[14] = LE_32(PMCS_SCRATCH_SIZE - rdoff);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[15] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh COPY_MESSAGE(ptr, msg, PMCS_MSG_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh htag = pwrk->htag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh WAIT_FOR(pwrk, 1000, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->config_changed) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh RESTART_DISCOVERY_LOCKED(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_timed_out(pwp, htag, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Issuing SMP ABORT for htag 0x%08x", __func__, htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_abort(pwp, pptr, htag, 0, 0)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Unable to issue SMP ABORT for htag 0x%08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Issuing SMP ABORT for htag 0x%08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr = (void *)pwp->scratch;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh status = LE_32(ptr[2]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (status == PMCOUT_STATUS_UNDERFLOW ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh status == PMCOUT_STATUS_OVERFLOW) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_UNDERFLOW,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: over/underflow", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh status = PMCOUT_STATUS_OK;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh srf = (smp_response_frame_t *)&((uint32_t *)pwp->scratch)[rdoff >> 2];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh srgr = (smp_report_general_resp_t *)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &((uint32_t *)pwp->scratch)[(rdoff >> 2)+1];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (status != PMCOUT_STATUS_OK) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char *nag = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(buf, sizeof (buf),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: SMP op failed (0x%x)", __func__, status);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (status) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_IO_PORT_IN_RESET:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DFM(nag, "I/O Port In Reset");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* FALLTHROUGH */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_ERROR_HW_TIMEOUT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DFM(nag, "Hardware Timeout");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* FALLTHROUGH */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_ERROR_INTERNAL_SMP_RESOURCE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DFM(nag, "Internal SMP Resource Failure");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* FALLTHROUGH */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERR_PHY_NOT_READY:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DFM(nag, "PHY Not Ready");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* FALLTHROUGH */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DFM(nag, "Connection Rate Not Supported");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* FALLTHROUGH */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_IO_XFER_OPEN_RETRY_TIMEOUT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DFM(nag, "Open Retry Timeout");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* FALLTHROUGH */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_SMP_RESP_CONNECTION_ERROR:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DFM(nag, "Response Connection Error");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: expander %s SMP operation failed (%s)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path, nag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * For the IO_DS_NON_OPERATIONAL case, we need to kick off
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * device state recovery and return 0 so that the caller
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * doesn't assume this expander is dead for good.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_IO_DS_NON_OPERATIONAL: {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *xp = pptr->target;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: expander %s device state non-operational",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: No target to do DS recovery for PHY "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%p (%s), attempting PHY hard reset",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)pptr, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_reset_phy(pwp, pptr,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_PHYOP_HARD_RESET);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_start_dev_state_recovery(xp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_print_entry(pwp, PMCS_PRT_DEBUG, buf, ptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = -EIO;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (srf->srf_frame_type != SMP_FRAME_TYPE_RESPONSE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: bad response frame type 0x%x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, srf->srf_frame_type);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = -EINVAL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (srf->srf_function != SMP_FUNC_REPORT_GENERAL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: bad response function 0x%x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, srf->srf_function);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = -EINVAL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (srf->srf_result != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Check to see if we have a value of 3 for failure and
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * whether we were using a SAS2.0 allocation length value
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * and retry without it.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (srf->srf_result == 3 && (ival & 0xff00)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ival &= ~0xff00;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: err 0x%x with SAS2 request- retry with SAS1",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, srf->srf_result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto again;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: bad response 0x%x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, srf->srf_result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = -EINVAL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (srgr->srgr_configuring) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: expander at phy %s is still configuring",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = srgr->srgr_number_of_phys;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ival & 0xff00) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->tolerates_sas2 = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s has %d phys and %s SAS2", pptr->path, result,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->tolerates_sas2? "tolerates" : "does not tolerate");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhout:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with expander locked (and thus, pptr) as well as all PHYs up to
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the root, and scratch acquired. Return 0 if we fail to allocate resources
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * or notice that the configuration changed while we were running the command.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We return less than zero if we had an I/O error or received an
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * unsupported configuration.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_expander_content_discover(pmcs_hw_t *pwp, pmcs_phy_t *expander,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct pmcwork *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char buf[64];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t sas_address[8];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t att_sas_address[8];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh smp_response_frame_t *srf;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh smp_discover_resp_t *sdr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh const uint_t rdoff = 0x100; /* returned data offset */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t *roff;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t status, *ptr, msg[PMCS_MSG_SIZE], htag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int result;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t ini_support;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t tgt_support;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, expander);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memset(pwp->scratch, 0x77, PMCS_SCRATCH_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->arg = pwp->scratch;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->dtype = expander->dtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL, PMCIN_SMP_REQUEST));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[2] = LE_32(expander->device_id);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[3] = LE_32((12 << SMP_REQUEST_LENGTH_SHIFT) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SMP_INDIRECT_RESPONSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Send SMP DISCOVER (of either SAS1.1 or SAS2 flavors).
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (expander->tolerates_sas2) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[4] = BE_32(0x40101B00);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[4] = BE_32(0x40100000);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[5] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[6] = BE_32((pptr->phynum << 16));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[7] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[8] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[9] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[10] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[11] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[12] = LE_32(DWORD0(pwp->scratch_dma+rdoff));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[13] = LE_32(DWORD1(pwp->scratch_dma+rdoff));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[14] = LE_32(PMCS_SCRATCH_SIZE - rdoff);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[15] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ptr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh COPY_MESSAGE(ptr, msg, PMCS_MSG_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh htag = pwrk->htag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Drop PHY lock while waiting so other completions aren't potentially
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * blocked.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(expander);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh WAIT_FOR(pwrk, 1000, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(expander);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->config_changed) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh RESTART_DISCOVERY_LOCKED(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_WARN, pmcs_timeo, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_abort(pwp, expander, htag, 0, 0)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Unable to issue SMP ABORT for htag 0x%08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Issuing SMP ABORT for htag 0x%08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = -ETIMEDOUT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr = (void *)pwp->scratch;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Point roff to the DMA offset for returned data
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh roff = pwp->scratch;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh roff += rdoff;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh srf = (smp_response_frame_t *)roff;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sdr = (smp_discover_resp_t *)(roff+4);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh status = LE_32(ptr[2]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (status == PMCOUT_STATUS_UNDERFLOW ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh status == PMCOUT_STATUS_OVERFLOW) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_UNDERFLOW,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: over/underflow", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh status = PMCOUT_STATUS_OK;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (status != PMCOUT_STATUS_OK) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char *nag = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(buf, sizeof (buf),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: SMP op failed (0x%x)", __func__, status);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (status) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_ERROR_HW_TIMEOUT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DFM(nag, "Hardware Timeout");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* FALLTHROUGH */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_ERROR_INTERNAL_SMP_RESOURCE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DFM(nag, "Internal SMP Resource Failure");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* FALLTHROUGH */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERR_PHY_NOT_READY:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DFM(nag, "PHY Not Ready");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* FALLTHROUGH */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DFM(nag, "Connection Rate Not Supported");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* FALLTHROUGH */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_IO_XFER_OPEN_RETRY_TIMEOUT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DFM(nag, "Open Retry Timeout");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* FALLTHROUGH */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_SMP_RESP_CONNECTION_ERROR:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DFM(nag, "Response Connection Error");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: expander %s SMP operation failed (%s)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path, nag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_print_entry(pwp, PMCS_PRT_DEBUG, buf, ptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = -EIO;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (srf->srf_frame_type != SMP_FRAME_TYPE_RESPONSE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: bad response frame type 0x%x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, srf->srf_frame_type);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = -EINVAL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (srf->srf_function != SMP_FUNC_DISCOVER) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: bad response function 0x%x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, srf->srf_function);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = -EINVAL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (srf->srf_result != SMP_RES_FUNCTION_ACCEPTED) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = pmcs_smp_function_result(pwp, srf);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Need not fail if PHY is Vacant */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result != SMP_RES_PHY_VACANT) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = -EINVAL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ini_support = (sdr->sdr_attached_sata_host |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (sdr->sdr_attached_smp_initiator << 1) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (sdr->sdr_attached_stp_initiator << 2) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (sdr->sdr_attached_ssp_initiator << 3));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt_support = (sdr->sdr_attached_sata_device |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (sdr->sdr_attached_smp_target << 1) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (sdr->sdr_attached_stp_target << 2) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (sdr->sdr_attached_ssp_target << 3));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wwn2barray(BE_64(sdr->sdr_sas_addr), sas_address);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wwn2barray(BE_64(sdr->sdr_attached_sas_addr), att_sas_address);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (sdr->sdr_attached_device_type) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_IF_DTYPE_ENDPOINT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "exp_content: %s atdt=0x%x lr=%x is=%x ts=%x SAS="
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SAS_ADDR_FMT " attSAS=" SAS_ADDR_FMT " atPHY=%x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->path,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sdr->sdr_attached_device_type,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sdr->sdr_negotiated_logical_link_rate,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ini_support,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt_support,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SAS_ADDR_PRT(sas_address),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SAS_ADDR_PRT(att_sas_address),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sdr->sdr_attached_phy_identifier);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (sdr->sdr_attached_sata_device ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sdr->sdr_attached_stp_target) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->dtype = SATA;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (sdr->sdr_attached_ssp_target) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->dtype = SAS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (tgt_support || ini_support) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "%s: %s has "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "tgt support=%x init support=(%x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path, tgt_support, ini_support);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_IF_DTYPE_EDGE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_IF_DTYPE_FANOUT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "exp_content: %s atdt=0x%x lr=%x is=%x ts=%x SAS="
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SAS_ADDR_FMT " attSAS=" SAS_ADDR_FMT " atPHY=%x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->path,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sdr->sdr_attached_device_type,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sdr->sdr_negotiated_logical_link_rate,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ini_support,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt_support,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SAS_ADDR_PRT(sas_address),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SAS_ADDR_PRT(att_sas_address),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sdr->sdr_attached_phy_identifier);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (sdr->sdr_attached_smp_target) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Avoid configuring phys that just point back
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * at a parent phy
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (expander->parent &&
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh memcmp(expander->parent->sas_address,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh att_sas_address,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sizeof (expander->parent->sas_address)) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG3,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: skipping port back to parent "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "expander (%s)", __func__, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->dtype = NOTHING;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->dtype = EXPANDER;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (tgt_support || ini_support) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, "%s has "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "tgt support=%x init support=(%x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->path, tgt_support, ini_support);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->dtype = EXPANDER;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->dtype = NOTHING;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->dtype != NOTHING) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *ctmp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the attached device is a SATA device and the expander
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * is (possibly) a SAS2 compliant expander, check for whether
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * there is a NAA=5 WWN field starting at this offset and
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * use that for the SAS Address for this device.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (expander->tolerates_sas2 && pptr->dtype == SATA &&
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (roff[SAS_ATTACHED_NAME_OFFSET] >> 8) == 0x5) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(pptr->sas_address,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &roff[SAS_ATTACHED_NAME_OFFSET], 8);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(pptr->sas_address, att_sas_address, 8);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->atdt = (sdr->sdr_attached_device_type);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Now run up from the expander's parent up to the top to
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * make sure we only use the least common link_rate.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (ctmp = expander->parent; ctmp; ctmp = ctmp->parent) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ctmp->link_rate <
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sdr->sdr_negotiated_logical_link_rate) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: derating link rate from %x to %x due "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "to %s being slower", pptr->path,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sdr->sdr_negotiated_logical_link_rate,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->link_rate,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sdr->sdr_negotiated_logical_link_rate =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->link_rate;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->link_rate = sdr->sdr_negotiated_logical_link_rate;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->state.prog_min_rate = sdr->sdr_prog_min_phys_link_rate;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->state.hw_min_rate = sdr->sdr_hw_min_phys_link_rate;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->state.prog_max_rate = sdr->sdr_prog_max_phys_link_rate;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->state.hw_max_rate = sdr->sdr_hw_max_phys_link_rate;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PHY_CHANGED(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_clear_phy(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhout:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Get a work structure and assign it a tag with type and serial number
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If a structure is returned, it is returned locked.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcwork_t *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_gwork(pmcs_hw_t *pwp, uint32_t tag_type, pmcs_phy_t *phyp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcwork_t *p;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint16_t snum;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t off;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->wfree_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p = STAILQ_FIRST(&pwp->wf);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (p == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we couldn't get a work structure, it's time to bite
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the bullet, grab the pfree_lock and copy over all the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * work structures from the pending free list to the actual
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * free list. This shouldn't happen all that often.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->pfree_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->wf.stqh_first = pwp->pf.stqh_first;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->wf.stqh_last = pwp->pf.stqh_last;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INIT(&pwp->pf);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->pfree_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p = STAILQ_FIRST(&pwp->wf);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (p == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->wfree_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_REMOVE(&pwp->wf, p, pmcwork, next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh snum = pwp->wserno++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->wfree_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh off = p - pwp->work;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&p->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(p->state == PMCS_WORK_STATE_NIL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(p->htag == PMCS_TAG_FREE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->htag = (tag_type << PMCS_TAG_TYPE_SHIFT) & PMCS_TAG_TYPE_MASK;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->htag |= ((snum << PMCS_TAG_SERNO_SHIFT) & PMCS_TAG_SERNO_MASK);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->htag |= ((off << PMCS_TAG_INDEX_SHIFT) & PMCS_TAG_INDEX_MASK);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->start = gethrtime();
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->state = PMCS_WORK_STATE_READY;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->ssp_event = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->dead = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->phy = phyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_inc_phy_ref_count(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (p);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with pwrk lock held. Returned with lock released.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_pwork(pmcs_hw_t *pwp, pmcwork_t *p)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(p != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&p->lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->last_ptr = p->ptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->last_arg = p->arg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->last_phy = p->phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->last_xp = p->xp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->last_htag = p->htag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->last_state = p->state;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->finish = gethrtime();
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (p->phy) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dec_phy_ref_count(p->phy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->state = PMCS_WORK_STATE_NIL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->htag = PMCS_TAG_FREE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->xp = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->ptr = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->arg = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->phy = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p->timer = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&p->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (mutex_tryenter(&pwp->wfree_lock) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->pfree_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_TAIL(&pwp->pf, p, next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->pfree_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_TAIL(&pwp->wf, p, next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->wfree_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Find a work structure based upon a tag and make sure that the tag
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * serial number matches the work structure we've found.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If a structure is found, its lock is held upon return.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcwork_t *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_tag2wp(pmcs_hw_t *pwp, uint32_t htag)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcwork_t *p;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t idx = PMCS_TAG_INDEX(htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh p = &pwp->work[idx];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&p->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (p->htag == htag) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (p);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&p->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG2, "INDEX 0x%x HTAG 0x%x got p->htag 0x%x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh idx, htag, p->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Issue an abort for a command or for all commands.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Since this can be called from interrupt context,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * we don't wait for completion if wait is not set.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with PHY lock held.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_abort(pmcs_hw_t *pwp, pmcs_phy_t *pptr, uint32_t tag, int all_cmds,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int wait)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcwork_t *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *tgt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t msg[PMCS_MSG_SIZE], *ptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int result, abt_type;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t abt_htag, status;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->abort_all_start) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: ABORT_ALL for (%s) already"
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh " in progress.", __func__, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EBUSY);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (pptr->dtype) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh abt_type = PMCIN_SSP_ABORT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SATA:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh abt_type = PMCIN_SATA_ABORT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case EXPANDER:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh abt_type = PMCIN_SMP_ABORT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk = pmcs_gwork(pwp, wait ? PMCS_TAG_TYPE_WAIT : PMCS_TAG_TYPE_NONE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nowrk, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ENOMEM);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->dtype = pptr->dtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (wait) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->arg = msg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->valid_device_id == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: Invalid DeviceID", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ENODEV);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL, abt_type));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[2] = LE_32(pptr->device_id);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (all_cmds) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[3] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[4] = LE_32(1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->ptr = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->abort_all_start = gethrtime();
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[3] = LE_32(tag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[4] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->ptr = &tag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ptr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nomsg, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ENOMEM);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh COPY_MESSAGE(ptr, msg, 5);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (all_cmds) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: aborting all commands for %s device %s. (htag=0x%x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pmcs_get_typename(pptr->dtype), pptr->path,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[1]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: aborting tag 0x%x for %s device %s. (htag=0x%x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, tag, pmcs_get_typename(pptr->dtype), pptr->path,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[1]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!wait) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh abt_htag = pwrk->htag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pwrk->phy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh WAIT_FOR(pwrk, 1000, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pwrk->phy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt = pwrk->xp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&tgt->aqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!STAILQ_EMPTY(&tgt->aq)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Abort complete (result=0x%x), but "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "aq not empty (tgt 0x%p), waiting",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, result, (void *)tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_wait(&tgt->abort_cv, &tgt->aqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->aqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (all_cmds) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->abort_all_start = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_signal(&pptr->abort_all_cv);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Abort (htag 0x%08x) request timed out",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, abt_htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((tgt->dev_state != PMCS_DEVICE_STATE_IN_RECOVERY) &&
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (tgt->dev_state !=
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_DEVICE_STATE_NON_OPERATIONAL)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Trying DS error recovery for tgt 0x%p",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_send_err_recovery_cmd(pwp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_DEVICE_STATE_IN_RECOVERY, tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ETIMEDOUT);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh status = LE_32(msg[2]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (status != PMCOUT_STATUS_OK) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The only non-success status are IO_NOT_VALID &
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * IO_ABORT_IN_PROGRESS.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * In case of IO_ABORT_IN_PROGRESS, the other ABORT cmd's
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * status is of concern and this duplicate cmd status can
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * be ignored.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If IO_NOT_VALID, that's not an error per-se.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * For abort of single I/O complete the command anyway.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If, however, we were aborting all, that is a problem
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * as IO_NOT_VALID really means that the IO or device is
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * not there. So, discovery process will take of the cleanup.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: abort result 0x%x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, LE_32(msg[2]));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (all_cmds) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PHY_CHANGED(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh RESTART_DISCOVERY(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EINVAL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt->dev_state == PMCS_DEVICE_STATE_IN_RECOVERY) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Restoring OPERATIONAL dev_state for tgt 0x%p",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_send_err_recovery_cmd(pwp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_DEVICE_STATE_OPERATIONAL, tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Issue a task management function to an SSP device.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with PHY lock held.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * statlock CANNOT be held upon entry.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_ssp_tmf(pmcs_hw_t *pwp, pmcs_phy_t *pptr, uint8_t tmf, uint32_t tag,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint64_t lun, uint32_t *response)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int result, ds;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t local[PMCS_QENTRY_SIZE << 1], *xd;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sas_ssp_rsp_iu_t *rptr = (void *)local;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh static const uint8_t ssp_rsp_evec[] = {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 0x58, 0x61, 0x56, 0x72, 0x00
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh };
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t msg[PMCS_MSG_SIZE], *ptr, status;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct pmcwork *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *xp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nowrk, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ENOMEM);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * NB: We use the PMCS_OQ_GENERAL outbound queue
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * NB: so as to not get entangled in normal I/O
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * NB: processing.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCIN_SSP_INI_TM_START));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[2] = LE_32(pptr->device_id);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tmf == SAS_ABORT_TASK || tmf == SAS_QUERY_TASK) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[3] = LE_32(tag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[3] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[4] = LE_32(tmf);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[5] = BE_32((uint32_t)lun);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[6] = BE_32((uint32_t)(lun >> 32));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[7] = LE_32(PMCIN_MESSAGE_REPORT);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ptr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nomsg, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ENOMEM);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh COPY_MESSAGE(ptr, msg, 7);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->arg = msg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->dtype = pptr->dtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp = pptr->target;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->dev_state == PMCS_DEVICE_STATE_NON_OPERATIONAL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: Not sending '%s'"
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh " because DS is '%s'", __func__, pmcs_tmf2str(tmf),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_status_str
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (PMCOUT_STATUS_IO_DS_NON_OPERATIONAL));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: sending '%s' to %s (lun %llu) tag 0x%x", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_tmf2str(tmf), pptr->path, (unsigned long long) lun, tag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This is a command sent to the target device, so it can take
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * significant amount of time to complete when path & device is busy.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Set a timeout to 20 seconds
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh WAIT_FOR(pwrk, 20000, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ETIMEDOUT);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_start_dev_state_recovery(xp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ETIMEDOUT);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh status = LE_32(msg[2]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (status != PMCOUT_STATUS_OK) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: status %s for TMF %s action to %s, lun %llu",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pmcs_status_str(status), pmcs_tmf2str(tmf),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->path, (unsigned long long) lun);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((status == PMCOUT_STATUS_IO_DS_NON_OPERATIONAL) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (status == PMCOUT_STATUS_OPEN_CNX_ERROR_BREAK) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (status == PMCOUT_STATUS_OPEN_CNX_ERROR_IT_NEXUS_LOSS)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ds = PMCS_DEVICE_STATE_NON_OPERATIONAL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (status == PMCOUT_STATUS_IO_DS_IN_RECOVERY) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the status is IN_RECOVERY, it's an indication
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * that it's now time for us to request to have the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * device state set to OPERATIONAL since we're the ones
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * that requested recovery to begin with.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ds = PMCS_DEVICE_STATE_OPERATIONAL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ds = PMCS_DEVICE_STATE_IN_RECOVERY;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->dev_state != ds) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Sending err recovery cmd"
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh " for tgt 0x%p (status = %s)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_status_str(status));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_send_err_recovery_cmd(pwp, ds, xp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ds = PMCS_DEVICE_STATE_OPERATIONAL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->dev_state != ds) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Sending err recovery cmd"
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh " for tgt 0x%p (status = %s)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_status_str(status));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_send_err_recovery_cmd(pwp, ds, xp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (LE_32(msg[3]) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "TMF completed with no response");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_endian_transform(pwp, local, &msg[5], ssp_rsp_evec);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xd = (uint8_t *)(&msg[5]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xd += SAS_RSP_HDR_SIZE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rptr->datapres != SAS_RSP_DATAPRES_RESPONSE_DATA) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: TMF response not RESPONSE DATA (0x%x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, rptr->datapres);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rptr->response_data_length != 4) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_print_entry(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Bad SAS RESPONSE DATA LENGTH", msg);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(&status, xd, sizeof (uint32_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh status = BE_32(status);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (response != NULL)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *response = status;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The status is actually in the low-order byte. The upper three
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * bytes contain additional information for the TMFs that support them.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * However, at this time we do not issue any of those. In the other
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * cases, the upper three bytes are supposed to be 0, but it appears
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * they aren't always. Just mask them off.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (status & 0xff) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_RSP_TMF_COMPLETE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: TMF complete", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_RSP_TMF_SUCCEEDED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: TMF succeeded", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_RSP_INVALID_FRAME:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: TMF returned INVALID FRAME", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = EIO;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_RSP_TMF_NOT_SUPPORTED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: TMF returned TMF NOT SUPPORTED", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = EIO;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_RSP_TMF_FAILED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: TMF returned TMF FAILED", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = EIO;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_RSP_TMF_INCORRECT_LUN:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: TMF returned INCORRECT LUN", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = EIO;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_RSP_OVERLAPPED_OIPTTA:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: TMF returned OVERLAPPED INITIATOR PORT TRANSFER TAG "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "ATTEMPTED", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = EIO;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: TMF returned unknown code 0x%x", __func__, status);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = EIO;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with PHY lock held and scratch acquired
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_sata_abort_ncq(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh const char *utag_fail_fmt = "%s: untagged NCQ command failure";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh const char *tag_fail_fmt = "%s: NCQ command failure (tag 0x%x)";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t msg[PMCS_QENTRY_SIZE], *ptr, result, status;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t *fp = pwp->scratch, ds;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis_t fis;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcwork_t *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *tgt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ENOMEM);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[0] = LE_32(PMCS_IOMB_IN_SAS(PMCS_OQ_IODONE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCIN_SATA_HOST_IO_START));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[2] = LE_32(pptr->device_id);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[3] = LE_32(512);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[4] = LE_32(SATA_PROTOCOL_PIO | PMCIN_DATADIR_2_INI);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[5] = LE_32((READ_LOG_EXT << 16) | (C_BIT << 8) | FIS_REG_H2DEV);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[6] = LE_32(0x10);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[8] = LE_32(1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[9] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[10] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[11] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[12] = LE_32(DWORD0(pwp->scratch_dma));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[13] = LE_32(DWORD1(pwp->scratch_dma));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[14] = LE_32(512);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[15] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->arg = msg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->dtype = pptr->dtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ptr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ENOMEM);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh COPY_MESSAGE(ptr, msg, PMCS_QENTRY_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh WAIT_FOR(pwrk, 250, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO, pmcs_timeo, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh status = LE_32(msg[2]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (status != PMCOUT_STATUS_OK || LE_32(msg[3])) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt = pptr->target;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: cannot find target for phy 0x%p for "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "dev state recovery", __func__, (void *)pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_print_entry(pwp, PMCS_PRT_DEBUG, "READ LOG EXT", msg);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((status == PMCOUT_STATUS_IO_DS_NON_OPERATIONAL) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (status == PMCOUT_STATUS_OPEN_CNX_ERROR_BREAK) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (status == PMCOUT_STATUS_OPEN_CNX_ERROR_IT_NEXUS_LOSS)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ds = PMCS_DEVICE_STATE_NON_OPERATIONAL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ds = PMCS_DEVICE_STATE_IN_RECOVERY;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt->dev_state != ds) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: Trying SATA DS Error"
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh " Recovery for tgt(0x%p) for status(%s)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)tgt, pmcs_status_str(status));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_send_err_recovery_cmd(pwp, ds, tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (EIO);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis[0] = (fp[4] << 24) | (fp[3] << 16) | (fp[2] << 8) | FIS_REG_D2H;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis[1] = (fp[8] << 24) | (fp[7] << 16) | (fp[6] << 8) | fp[5];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis[2] = (fp[12] << 24) | (fp[11] << 16) | (fp[10] << 8) | fp[9];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis[3] = (fp[16] << 24) | (fp[15] << 16) | (fp[14] << 8) | fp[13];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis[4] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (fp[0] & 0x80) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, utag_fail_fmt, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, tag_fail_fmt, __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fp[0] & 0x1f);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_fis_dump(pwp, fis);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->need_rl_ext = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Transform a structure from CPU to Device endian format, or
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * vice versa, based upon a transformation vector.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * A transformation vector is an array of bytes, each byte
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * of which is defined thusly:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * bit 7: from CPU to desired endian, otherwise from desired endian
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * to CPU format
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * bit 6: Big Endian, else Little Endian
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * bits 5-4:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * 00 Undefined
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * 01 One Byte quantities
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * 02 Two Byte quantities
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * 03 Four Byte quantities
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * bits 3-0:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * 00 Undefined
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Number of quantities to transform
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The vector is terminated by a 0 value.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_endian_transform(pmcs_hw_t *pwp, void *orig_out, void *orig_in,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh const uint8_t *xfvec)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t c, *out = orig_out, *in = orig_in;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xfvec == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: null xfvec", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (out == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: null out", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (in == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: null in", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while ((c = *xfvec++) != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int nbyt = (c & 0xf);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int size = (c >> 4) & 0x3;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int bige = (c >> 4) & 0x4;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (size) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case 1:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (nbyt-- > 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *out++ = *in++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case 2:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint16_t tmp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (nbyt-- > 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(&tmp, in, sizeof (uint16_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (bige) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tmp = BE_16(tmp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tmp = LE_16(tmp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(out, &tmp, sizeof (uint16_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh out += sizeof (uint16_t);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh in += sizeof (uint16_t);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case 3:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t tmp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (nbyt-- > 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(&tmp, in, sizeof (uint32_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (bige) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tmp = BE_32(tmp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tmp = LE_32(tmp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(out, &tmp, sizeof (uint32_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh out += sizeof (uint32_t);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh in += sizeof (uint32_t);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: bad size", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhconst char *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_get_rate(unsigned int linkrt)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh const char *rate;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (linkrt) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_LINK_RATE_1_5GBIT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rate = "1.5";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_LINK_RATE_3GBIT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rate = "3.0";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_LINK_RATE_6GBIT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rate = "6.0";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rate = "???";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (rate);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhconst char *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_get_typename(pmcs_dtype_t type)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (type) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case NOTHING:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("NIL");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SATA:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("SATA");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("SSP");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case EXPANDER:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("EXPANDER");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("????");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhconst char *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_tmf2str(int tmf)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (tmf) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_ABORT_TASK:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("Abort Task");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_ABORT_TASK_SET:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("Abort Task Set");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_CLEAR_TASK_SET:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("Clear Task Set");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_LOGICAL_UNIT_RESET:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("Logical Unit Reset");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_I_T_NEXUS_RESET:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("I_T Nexus Reset");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_CLEAR_ACA:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("Clear ACA");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_QUERY_TASK:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("Query Task");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_QUERY_TASK_SET:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("Query Task Set");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SAS_QUERY_UNIT_ATTENTION:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("Query Unit Attention");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("Unknown");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhconst char *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_status_str(uint32_t status)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (status) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OK:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("OK");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_ABORTED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("ABORTED");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OVERFLOW:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("OVERFLOW");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_UNDERFLOW:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("UNDERFLOW");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_FAILED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("FAILED");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_ABORT_RESET:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("ABORT_RESET");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_IO_NOT_VALID:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("IO_NOT_VALID");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_NO_DEVICE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("NO_DEVICE");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_ILLEGAL_PARAMETER:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("ILLEGAL_PARAMETER");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_LINK_FAILURE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("LINK_FAILURE");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_PROG_ERROR:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("PROG_ERROR");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_EDC_IN_ERROR:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("EDC_IN_ERROR");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_EDC_OUT_ERROR:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("EDC_OUT_ERROR");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_ERROR_HW_TIMEOUT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("ERROR_HW_TIMEOUT");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERR_BREAK:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("XFER_ERR_BREAK");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERR_PHY_NOT_READY:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("XFER_ERR_PHY_NOT_READY");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OPEN_CNX_PROTOCOL_NOT_SUPPORTED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("OPEN_CNX_PROTOCOL_NOT_SUPPORTED");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OPEN_CNX_ERROR_ZONE_VIOLATION:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("OPEN_CNX_ERROR_ZONE_VIOLATION");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OPEN_CNX_ERROR_BREAK:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("OPEN_CNX_ERROR_BREAK");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("OPEN_CNX_ERROR_IT_NEXUS_LOSS");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OPENCNX_ERROR_BAD_DESTINATION:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("OPENCNX_ERROR_BAD_DESTINATION");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("OPEN_CNX_ERROR_STP_RESOURCES_BUSY");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OPEN_CNX_ERROR_WRONG_DESTINATION:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("OPEN_CNX_ERROR_WRONG_DESTINATION");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OPEN_CNX_ERROR_UNKNOWN_EROOR:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("OPEN_CNX_ERROR_UNKNOWN_EROOR");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_IO_XFER_ERROR_NAK_RECEIVED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("IO_XFER_ERROR_NAK_RECEIVED");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_ACK_NAK_TIMEOUT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("XFER_ERROR_ACK_NAK_TIMEOUT");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_PEER_ABORTED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("XFER_ERROR_PEER_ABORTED");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_RX_FRAME:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("XFER_ERROR_RX_FRAME");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_IO_XFER_ERROR_DMA:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("IO_XFER_ERROR_DMA");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_CREDIT_TIMEOUT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("XFER_ERROR_CREDIT_TIMEOUT");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_SATA_LINK_TIMEOUT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("XFER_ERROR_SATA_LINK_TIMEOUT");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_SATA:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("XFER_ERROR_SATA");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_REJECTED_NCQ_MODE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("XFER_ERROR_REJECTED_NCQ_MODE");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_ABORTED_DUE_TO_SRST:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("XFER_ERROR_ABORTED_DUE_TO_SRST");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_ABORTED_NCQ_MODE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("XFER_ERROR_ABORTED_NCQ_MODE");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_IO_XFER_OPEN_RETRY_TIMEOUT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("IO_XFER_OPEN_RETRY_TIMEOUT");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_SMP_RESP_CONNECTION_ERROR:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("SMP_RESP_CONNECTION_ERROR");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_UNEXPECTED_PHASE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("XFER_ERROR_UNEXPECTED_PHASE");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_RDY_OVERRUN:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("XFER_ERROR_RDY_OVERRUN");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_RDY_NOT_EXPECTED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("XFER_ERROR_RDY_NOT_EXPECTED");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_CMD_ISSUE_BREAK_BEFORE_ACK_NACK:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("XFER_ERROR_CMD_ISSUE_BREAK_BEFORE_ACK_NACK");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_CMD_ISSUE_PHY_DOWN_BEFORE_ACK_NAK:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("XFER_ERROR_CMD_ISSUE_PHY_DOWN_BEFORE_ACK_NAK");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_OFFSET_MISMATCH:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("XFER_ERROR_OFFSET_MISMATCH");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_ZERO_DATA_LEN:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("XFER_ERROR_ZERO_DATA_LEN");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_CMD_FRAME_ISSUED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("XFER_CMD_FRAME_ISSUED");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_ERROR_INTERNAL_SMP_RESOURCE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("ERROR_INTERNAL_SMP_RESOURCE");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_IO_PORT_IN_RESET:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("IO_PORT_IN_RESET");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_IO_DS_NON_OPERATIONAL:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("DEVICE STATE NON-OPERATIONAL");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_IO_DS_IN_RECOVERY:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return ("DEVICE STATE IN RECOVERY");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhuint64_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_barray2wwn(uint8_t ba[8])
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint64_t result = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int i;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < 8; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result <<= 8;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result |= ba[i];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_wwn2barray(uint64_t wwn, uint8_t ba[8])
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int i;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < 8; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ba[7 - i] = wwn & 0xff;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh wwn >>= 8;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_report_fwversion(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh const char *fwsupport;
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 pmcs_prt(pwp, PMCS_PRT_INFO,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Chip Revision: %c; F/W Revision %x.%x.%x %s", 'A' + pwp->chiprev,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_FW_MAJOR(pwp), PMCS_FW_MINOR(pwp), PMCS_FW_MICRO(pwp),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fwsupport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_phy_name(pmcs_hw_t *pwp, pmcs_phy_t *pptr, char *obuf, size_t olen)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->parent) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_name(pwp, pptr->parent, obuf, olen);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(obuf, olen, "%s.%02x", obuf, pptr->phynum);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(obuf, olen, "pp%02x", pptr->phynum);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Implementation for pmcs_find_phy_by_devid.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the PHY is found, it is returned locked.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic pmcs_phy_t *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_find_phy_by_devid_impl(pmcs_phy_t *phyp, uint32_t device_id)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *match, *cphyp, *nphyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(!mutex_owned(&phyp->phy_lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (phyp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((phyp->valid_device_id) && (phyp->device_id == device_id)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp->children) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cphyp = phyp->children;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh match = pmcs_find_phy_by_devid_impl(cphyp, device_id);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (match) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&match->phy_lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (match);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (IS_ROOT_PHY(phyp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh nphyp = phyp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = nphyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the PHY is found, it is returned locked
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_phy_t *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_find_phy_by_devid(pmcs_hw_t *pwp, uint32_t device_id)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *phyp, *match = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = pwp->root_phys;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (phyp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh match = pmcs_find_phy_by_devid_impl(phyp, device_id);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (match) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&match->phy_lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (match);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = phyp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This function is called as a sanity check to ensure that a newly registered
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * PHY doesn't have a device_id that exists with another registered PHY.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic boolean_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_validate_devid(pmcs_phy_t *parent, pmcs_phy_t *phyp, uint32_t device_id)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh boolean_t rval;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = parent;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (pptr) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->valid_device_id && (pptr != phyp) &&
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pptr->device_id == device_id)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pptr->pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: phy %s already exists as %s with "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "device id 0x%x", __func__, phyp->path,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->path, device_id);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->children) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = pmcs_validate_devid(pptr->children, phyp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh device_id);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rval == B_FALSE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (rval);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pptr->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* This PHY and device_id are valid */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the PHY is found, it is returned locked
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic pmcs_phy_t *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_find_phy_by_wwn_impl(pmcs_phy_t *phyp, uint8_t *wwn)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *matched_phy, *cphyp, *nphyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(!mutex_owned(&phyp->phy_lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (phyp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp->valid_device_id) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (memcmp(phyp->sas_address, wwn, 8) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp->children) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cphyp = phyp->children;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh matched_phy = pmcs_find_phy_by_wwn_impl(cphyp, wwn);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (matched_phy) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&matched_phy->phy_lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (matched_phy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Only iterate through non-root PHYs
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (IS_ROOT_PHY(phyp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh nphyp = phyp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = nphyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_phy_t *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_find_phy_by_wwn(pmcs_hw_t *pwp, uint64_t wwn)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t ebstr[8];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr, *matched_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wwn2barray(wwn, ebstr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pwp->root_phys;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (pptr) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh matched_phy = pmcs_find_phy_by_wwn_impl(pptr, ebstr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (matched_phy) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&matched_phy->phy_lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (matched_phy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pptr->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * pmcs_find_phy_by_sas_address
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Find a PHY that both matches "sas_addr" and is on "iport".
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If a matching PHY is found, it is returned locked.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_phy_t *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_find_phy_by_sas_address(pmcs_hw_t *pwp, pmcs_iport_t *iport,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *root, char *sas_addr)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int ua_form = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint64_t wwn;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char addr[PMCS_MAX_UA_SIZE];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr, *pnext, *pchild;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (root == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pwp->root_phys;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = root;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (pptr) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the PHY is dead or does not have a valid device ID,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * skip it.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((pptr->dead) || (!pptr->valid_device_id)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->iport != iport) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh wwn = pmcs_barray2wwn(pptr->sas_address);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *) scsi_wwn_to_wwnstr(wwn, ua_form, addr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (strncmp(addr, sas_addr, strlen(addr)) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->children) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pchild = pptr->children;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pnext = pmcs_find_phy_by_sas_address(pwp, iport, pchild,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sas_addr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pnext) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (pnext);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhnext_phy:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pnext = pptr->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pnext;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_fis_dump(pmcs_hw_t *pwp, fis_t fis)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (fis[0] & 0xff) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case FIS_REG_H2DEV:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO, "FIS REGISTER HOST TO DEVICE: "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "OP=0x%02x Feature=0x%04x Count=0x%04x Device=0x%02x "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "LBA=%llu", BYTE2(fis[0]), BYTE3(fis[2]) << 8 |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh BYTE3(fis[0]), WORD0(fis[3]), BYTE3(fis[1]),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (unsigned long long)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((uint64_t)fis[2] & 0x00ffffff) << 24 |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ((uint64_t)fis[1] & 0x00ffffff)));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case FIS_REG_D2H:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO, "FIS REGISTER DEVICE TO HOST: Stat"
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "us=0x%02x Error=0x%02x Dev=0x%02x Count=0x%04x LBA=%llu",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh BYTE2(fis[0]), BYTE3(fis[0]), BYTE3(fis[1]), WORD0(fis[3]),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (unsigned long long)(((uint64_t)fis[2] & 0x00ffffff) << 24 |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ((uint64_t)fis[1] & 0x00ffffff)));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_INFO, "FIS: 0x%08x 0x%08x 0x%08x 0x%08x "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "0x%08x 0x%08x 0x%08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis[0], fis[1], fis[2], fis[3], fis[4], fis[5], fis[6]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_print_entry(pmcs_hw_t *pwp, int level, char *msg, void *arg)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t *mb = arg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh size_t i;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, level, msg);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < (PMCS_QENTRY_SIZE / sizeof (uint32_t)); i += 4) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, level, "Offset %2lu: 0x%08x 0x%08x 0x%08"
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "x 0x%08x", i * sizeof (uint32_t), LE_32(mb[i]),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh LE_32(mb[i+1]), LE_32(mb[i+2]),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh LE_32(mb[i+3]));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If phyp == NULL we're being called from the worker thread, in which
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * case we need to check all the PHYs. In this case, the softstate lock
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * will be held.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If phyp is non-NULL, just issue the spinup release for the specified PHY
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * (which will already be locked).
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_spinup_release(pmcs_hw_t *pwp, pmcs_phy_t *phyp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t *msg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct pmcwork *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *tphyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&phyp->phy_lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Issuing spinup release only for PHY %s", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (msg == NULL || (pwrk =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_gwork(pwp, PMCS_TAG_TYPE_NONE, NULL)) == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_SPINUP_RELEASE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp->spinup_hold = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(msg, PMCS_QENTRY_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCIN_LOCAL_PHY_CONTROL));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[2] = LE_32((0x10 << 8) | phyp->phynum);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->dtype = phyp->dtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&pwp->lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tphyp = pwp->root_phys;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (tphyp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(tphyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tphyp->spinup_hold == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(tphyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tphyp = tphyp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Issuing spinup release for PHY %s", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (msg == NULL || (pwrk =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_gwork(pwp, PMCS_TAG_TYPE_NONE, NULL)) == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(tphyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_SPINUP_RELEASE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tphyp->spinup_hold = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(msg, PMCS_QENTRY_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCIN_LOCAL_PHY_CONTROL));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[2] = LE_32((0x10 << 8) | tphyp->phynum);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->dtype = phyp->dtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(tphyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tphyp = tphyp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Abort commands on dead PHYs and deregister them as well as removing
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the associated targets.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_kill_devices(pmcs_hw_t *pwp, pmcs_phy_t *phyp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pnext, *pchild;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh boolean_t remove_device;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int rval = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (phyp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pchild = phyp->children;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pnext = phyp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pchild) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = pmcs_kill_devices(pwp, pchild);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rval) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (rval);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * pmcs_remove_device requires the softstate lock.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp->dead && phyp->valid_device_id) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh remove_device = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh remove_device = B_FALSE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (remove_device) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_remove_device(pwp, phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = pmcs_kill_device(pwp, phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rval) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (rval);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = pnext;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (rval);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with PHY locked
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_kill_device(pmcs_hw_t *pwp, pmcs_phy_t *pptr)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int r, result;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t msg[PMCS_MSG_SIZE], *ptr, status;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct pmcwork *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *tgt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "kill %s device @ %s",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_get_typename(pptr->dtype), pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * There may be an outstanding ABORT_ALL running, which we wouldn't
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * know just by checking abort_pending. We can, however, check
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * abort_all_start. If it's non-zero, there is one, and we'll just
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * sit here and wait for it to complete. If we don't, we'll remove
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the device while there are still commands pending.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->abort_all_start) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (pptr->abort_all_start) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Waiting for outstanding ABORT_ALL on PHY 0x%p",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_wait(&pptr->abort_all_cv, &pptr->phy_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (pptr->abort_pending) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh r = pmcs_abort(pwp, pptr, pptr->device_id, 1, 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (r) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: ABORT_ALL returned non-zero status (%d) for "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "PHY 0x%p", __func__, r, (void *)pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (r);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->abort_pending = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Now that everything is aborted from the chip's perspective (or even
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * if it is not), flush out the wait queue. We won't flush the active
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * queue since it is possible that abort completions may follow after
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the notification that the abort all has completed.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt = pptr->target;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_flush_target_queues(pwp, tgt, PMCS_TGT_WAIT_QUEUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->valid_device_id == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr)) == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nowrk, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ENOMEM);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->arg = msg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->dtype = pptr->dtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCIN_DEREGISTER_DEVICE_HANDLE));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[2] = LE_32(pptr->device_id);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ptr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nomsg, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ENOMEM);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh COPY_MESSAGE(ptr, msg, 3);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh WAIT_FOR(pwrk, 250, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ETIMEDOUT);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh status = LE_32(msg[2]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (status != PMCOUT_STATUS_OK) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: status 0x%x when trying to deregister device %s",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, status, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->device_id = PMCS_INVALID_DEVICE_ID;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PHY_CHANGED(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh RESTART_DISCOVERY(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->valid_device_id = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Acknowledge the SAS h/w events that need acknowledgement.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This is only needed for first level PHYs.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_ack_events(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t msg[PMCS_MSG_SIZE], *ptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct pmcwork *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (pptr = pwp->root_phys; pptr; pptr = pptr->sibling) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->hw_event_ack == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((ptr == NULL) || (pwrk =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_gwork(pwp, PMCS_TAG_TYPE_NONE, NULL)) == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_SAS_HW_ACK);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCIN_SAW_HW_EVENT_ACK));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[2] = LE_32(pptr->hw_event_ack);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->dtype = pptr->dtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->hw_event_ack = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh COPY_MESSAGE(ptr, msg, 3);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Load DMA
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_dma_load(pmcs_hw_t *pwp, pmcs_cmd_t *sp, uint32_t *msg)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_dma_cookie_t *sg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dmachunk_t *tc;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dmasgl_t *sgl, *prior;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int seg, tsc;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint64_t sgl_addr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we have no data segments, we're done.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (CMD2PKT(sp)->pkt_numcookies == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Get the S/G list pointer.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sg = CMD2PKT(sp)->pkt_cookies;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we only have one dma segment, we can directly address that
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * data within the Inbound message itself.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (CMD2PKT(sp)->pkt_numcookies == 1) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[12] = LE_32(DWORD0(sg->dmac_laddress));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[13] = LE_32(DWORD1(sg->dmac_laddress));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[14] = LE_32(sg->dmac_size);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[15] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Otherwise, we'll need one or more external S/G list chunks.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Get the first one and its dma address into the Inbound message.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->dma_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tc = pwp->dma_freelist;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tc == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_ADD_DMA_CHUNKS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->dma_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG2, "%s: out of SG lists", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->dma_freelist = tc->nxt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->dma_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tc->nxt = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sp->cmd_clist = tc;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sgl = tc->chunks;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memset(tc->chunks, 0, PMCS_SGL_CHUNKSZ);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sgl_addr = tc->addr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[12] = LE_32(DWORD0(sgl_addr));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[13] = LE_32(DWORD1(sgl_addr));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[14] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[15] = LE_32(PMCS_DMASGL_EXTENSION);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh prior = sgl;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tsc = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (seg = 0; seg < CMD2PKT(sp)->pkt_numcookies; seg++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the current segment count for this chunk is one less than
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the number s/g lists per chunk and we have more than one seg
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * to go, we need another chunk. Get it, and make sure that the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * tail end of the the previous chunk points the new chunk
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * (if remembering an offset can be called 'pointing to').
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Note that we can store the offset into our command area that
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * represents the new chunk in the length field of the part
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * that points the PMC chip at the next chunk- the PMC chip
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * ignores this field when the EXTENSION bit is set.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This is required for dma unloads later.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tsc == (PMCS_SGL_NCHUNKS - 1) &&
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh seg < (CMD2PKT(sp)->pkt_numcookies - 1)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->dma_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tc = pwp->dma_freelist;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tc == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_ADD_DMA_CHUNKS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->dma_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dma_unload(pwp, sp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG2,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: out of SG lists", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->dma_freelist = tc->nxt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tc->nxt = sp->cmd_clist;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->dma_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sp->cmd_clist = tc;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memset(tc->chunks, 0, PMCS_SGL_CHUNKSZ);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sgl = tc->chunks;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sgl_addr = tc->addr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh prior[PMCS_SGL_NCHUNKS-1].sglal =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh LE_32(DWORD0(sgl_addr));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh prior[PMCS_SGL_NCHUNKS-1].sglah =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh LE_32(DWORD1(sgl_addr));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh prior[PMCS_SGL_NCHUNKS-1].sglen = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh prior[PMCS_SGL_NCHUNKS-1].flags =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh LE_32(PMCS_DMASGL_EXTENSION);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh prior = sgl;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tsc = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sgl[tsc].sglal = LE_32(DWORD0(sg->dmac_laddress));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sgl[tsc].sglah = LE_32(DWORD1(sg->dmac_laddress));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sgl[tsc].sglen = LE_32(sg->dmac_size);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sgl[tsc++].flags = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sg++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Unload DMA
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_dma_unload(pmcs_hw_t *pwp, pmcs_cmd_t *sp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dmachunk_t *cp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->dma_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while ((cp = sp->cmd_clist) != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sp->cmd_clist = cp->nxt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cp->nxt = pwp->dma_freelist;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->dma_freelist = cp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->dma_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Take a chunk of consistent memory that has just been allocated and inserted
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * into the cip indices and prepare it for DMA chunk usage and add it to the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * freelist.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with dma_lock locked (except during attach when it's unnecessary)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_idma_chunks(pmcs_hw_t *pwp, pmcs_dmachunk_t *dcp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_chunk_t *pchunk, unsigned long lim)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh unsigned long off, n;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dmachunk_t *np = dcp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_chunk_t *tmp_chunk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->dma_chunklist == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->dma_chunklist = pchunk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tmp_chunk = pwp->dma_chunklist;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (tmp_chunk->next) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tmp_chunk = tmp_chunk->next;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tmp_chunk->next = pchunk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Install offsets into chunk lists.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (n = 0, off = 0; off < lim; off += PMCS_SGL_CHUNKSZ, n++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh np->chunks = (void *)&pchunk->addrp[off];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh np->addr = pchunk->dma_addr + off;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh np->acc_handle = pchunk->acc_handle;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh np->dma_handle = pchunk->dma_handle;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((off + PMCS_SGL_CHUNKSZ) < lim) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh np = np->nxt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh np->nxt = pwp->dma_freelist;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->dma_freelist = dcp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG2,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "added %lu DMA chunks ", n);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Change the value of the interrupt coalescing timer. This is done currently
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * only for I/O completions. If we're using the "auto clear" feature, it can
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * be turned back on when interrupt coalescing is turned off and must be
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * turned off when the coalescing timer is on.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * NOTE: PMCS_MSIX_GENERAL and PMCS_OQ_IODONE are the same value. As long
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * as that's true, we don't need to distinguish between them.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_set_intr_coal_timer(pmcs_hw_t *pwp, pmcs_coal_timer_adj_t adj)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (adj == DECREASE_TIMER) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* If the timer is already off, nothing to do. */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->io_intr_coal.timer_on == B_FALSE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->io_intr_coal.intr_coal_timer -= PMCS_COAL_TIMER_GRAN;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->io_intr_coal.intr_coal_timer == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Disable the timer */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_topunit(pwp, PMCS_INT_COALESCING_CONTROL, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->odb_auto_clear & (1 << PMCS_MSIX_IODONE)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_topunit(pwp, PMCS_OBDB_AUTO_CLR,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->odb_auto_clear);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->io_intr_coal.timer_on = B_FALSE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->io_intr_coal.max_io_completions = B_FALSE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->io_intr_coal.num_intrs = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->io_intr_coal.int_cleared = B_FALSE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->io_intr_coal.num_io_completions = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DTRACE_PROBE1(pmcs__intr__coalesce__timer__off,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_io_intr_coal_t *, &pwp->io_intr_coal);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_topunit(pwp, PMCS_INT_COALESCING_TIMER,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->io_intr_coal.intr_coal_timer);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the timer isn't on yet, do the setup for it now.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->io_intr_coal.timer_on == B_FALSE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* If auto clear is being used, turn it off. */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->odb_auto_clear & (1 << PMCS_MSIX_IODONE)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_topunit(pwp, PMCS_OBDB_AUTO_CLR,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pwp->odb_auto_clear &
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ~(1 << PMCS_MSIX_IODONE)));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_topunit(pwp, PMCS_INT_COALESCING_CONTROL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (1 << PMCS_MSIX_IODONE));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->io_intr_coal.timer_on = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->io_intr_coal.intr_coal_timer =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_COAL_TIMER_GRAN;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DTRACE_PROBE1(pmcs__intr__coalesce__timer__on,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_io_intr_coal_t *, &pwp->io_intr_coal);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->io_intr_coal.intr_coal_timer +=
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_COAL_TIMER_GRAN;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->io_intr_coal.intr_coal_timer > PMCS_MAX_COAL_TIMER) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->io_intr_coal.intr_coal_timer = PMCS_MAX_COAL_TIMER;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_topunit(pwp, PMCS_INT_COALESCING_TIMER,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->io_intr_coal.intr_coal_timer);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Adjust the interrupt threshold based on the current timer value
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->io_intr_coal.intr_threshold =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_INTR_THRESHOLD(PMCS_QUANTUM_TIME_USECS * 1000 /
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pwp->io_intr_coal.intr_latency +
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pwp->io_intr_coal.intr_coal_timer * 1000)));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Register Access functions
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhuint32_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_rd_iqci(pmcs_hw_t *pwp, uint32_t qnum)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t iqci;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_dma_sync(pwp->cip_handles, 0, 0, DDI_DMA_SYNC_FORKERNEL) !=
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: ddi_dma_sync failed?",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iqci = LE_32(
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ((uint32_t *)((void *)pwp->cip))[IQ_OFFSET(qnum) >> 2]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (iqci);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhuint32_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_rd_oqpi(pmcs_hw_t *pwp, uint32_t qnum)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t oqpi;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_dma_sync(pwp->cip_handles, 0, 0, DDI_DMA_SYNC_FORKERNEL) !=
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: ddi_dma_sync failed?",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh oqpi = LE_32(
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ((uint32_t *)((void *)pwp->cip))[OQ_OFFSET(qnum) >> 2]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (oqpi);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhuint32_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_rd_gsm_reg(pmcs_hw_t *pwp, uint32_t off)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t rv, newaxil, oldaxil;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh newaxil = off & ~GSM_BASE_MASK;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh off &= GSM_BASE_MASK;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->axil_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh oldaxil = ddi_get32(pwp->top_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->top_regs[PMCS_AXI_TRANS >> 2]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_put32(pwp->top_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->top_regs[PMCS_AXI_TRANS >> 2], newaxil);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(10);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_get32(pwp->top_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != newaxil) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "AXIL register update failed");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rv = ddi_get32(pwp->gsm_acc_handle, &pwp->gsm_regs[off >> 2]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_put32(pwp->top_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->top_regs[PMCS_AXI_TRANS >> 2], oldaxil);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(10);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_get32(pwp->top_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != oldaxil) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "AXIL register restore failed");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->axil_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (rv);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_wr_gsm_reg(pmcs_hw_t *pwp, uint32_t off, uint32_t val)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t newaxil, oldaxil;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh newaxil = off & ~GSM_BASE_MASK;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh off &= GSM_BASE_MASK;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->axil_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh oldaxil = ddi_get32(pwp->top_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->top_regs[PMCS_AXI_TRANS >> 2]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_put32(pwp->top_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->top_regs[PMCS_AXI_TRANS >> 2], newaxil);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(10);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_get32(pwp->top_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != newaxil) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "AXIL register update failed");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_put32(pwp->gsm_acc_handle, &pwp->gsm_regs[off >> 2], val);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_put32(pwp->top_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->top_regs[PMCS_AXI_TRANS >> 2], oldaxil);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh drv_usecwait(10);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_get32(pwp->top_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->top_regs[PMCS_AXI_TRANS >> 2]) != oldaxil) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "AXIL register restore failed");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->axil_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhuint32_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_rd_topunit(pmcs_hw_t *pwp, uint32_t off)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (off) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_SPC_RESET:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_SPC_BOOT_STRAP:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_SPC_DEVICE_ID:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_DEVICE_REVISION:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh off = pmcs_rd_gsm_reg(pwp, off);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh off = ddi_get32(pwp->top_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->top_regs[off >> 2]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (off);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_wr_topunit(pmcs_hw_t *pwp, uint32_t off, uint32_t val)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (off) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_SPC_RESET:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_DEVICE_REVISION:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_wr_gsm_reg(pwp, off, val);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_put32(pwp->top_acc_handle, &pwp->top_regs[off >> 2], val);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhuint32_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_rd_msgunit(pmcs_hw_t *pwp, uint32_t off)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ddi_get32(pwp->msg_acc_handle, &pwp->msg_regs[off >> 2]));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhuint32_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_rd_mpi_tbl(pmcs_hw_t *pwp, uint32_t off)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ddi_get32(pwp->mpi_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->mpi_regs[(pwp->mpi_offset + off) >> 2]));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhuint32_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_rd_gst_tbl(pmcs_hw_t *pwp, uint32_t off)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ddi_get32(pwp->mpi_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->mpi_regs[(pwp->mpi_gst_offset + off) >> 2]));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhuint32_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_rd_iqc_tbl(pmcs_hw_t *pwp, uint32_t off)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ddi_get32(pwp->mpi_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->mpi_regs[(pwp->mpi_iqc_offset + off) >> 2]));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhuint32_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_rd_oqc_tbl(pmcs_hw_t *pwp, uint32_t off)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ddi_get32(pwp->mpi_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->mpi_regs[(pwp->mpi_oqc_offset + off) >> 2]));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhuint32_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_rd_iqpi(pmcs_hw_t *pwp, uint32_t qnum)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ddi_get32(pwp->mpi_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->mpi_regs[pwp->iqpi_offset[qnum] >> 2]));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhuint32_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_rd_oqci(pmcs_hw_t *pwp, uint32_t qnum)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (ddi_get32(pwp->mpi_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->mpi_regs[pwp->oqci_offset[qnum] >> 2]));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_wr_msgunit(pmcs_hw_t *pwp, uint32_t off, uint32_t val)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_put32(pwp->msg_acc_handle, &pwp->msg_regs[off >> 2], val);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_wr_mpi_tbl(pmcs_hw_t *pwp, uint32_t off, uint32_t val)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_put32(pwp->mpi_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->mpi_regs[(pwp->mpi_offset + off) >> 2], (val));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_wr_gst_tbl(pmcs_hw_t *pwp, uint32_t off, uint32_t val)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_put32(pwp->mpi_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->mpi_regs[(pwp->mpi_gst_offset + off) >> 2], val);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_wr_iqc_tbl(pmcs_hw_t *pwp, uint32_t off, uint32_t val)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_put32(pwp->mpi_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->mpi_regs[(pwp->mpi_iqc_offset + off) >> 2], val);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_wr_oqc_tbl(pmcs_hw_t *pwp, uint32_t off, uint32_t val)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_put32(pwp->mpi_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->mpi_regs[(pwp->mpi_oqc_offset + off) >> 2], val);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_wr_iqci(pmcs_hw_t *pwp, uint32_t qnum, uint32_t val)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ((uint32_t *)((void *)pwp->cip))[IQ_OFFSET(qnum) >> 2] = val;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_dma_sync(pwp->cip_handles, 0, 0, DDI_DMA_SYNC_FORDEV) !=
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: ddi_dma_sync failed?",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_wr_iqpi(pmcs_hw_t *pwp, uint32_t qnum, uint32_t val)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_put32(pwp->mpi_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->mpi_regs[pwp->iqpi_offset[qnum] >> 2], val);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_wr_oqci(pmcs_hw_t *pwp, uint32_t qnum, uint32_t val)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_put32(pwp->mpi_acc_handle,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->mpi_regs[pwp->oqci_offset[qnum] >> 2], val);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_wr_oqpi(pmcs_hw_t *pwp, uint32_t qnum, uint32_t val)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ((uint32_t *)((void *)pwp->cip))[OQ_OFFSET(qnum) >> 2] = val;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_dma_sync(pwp->cip_handles, 0, 0, DDI_DMA_SYNC_FORDEV) !=
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: ddi_dma_sync failed?",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Check the status value of an outbound IOMB and report anything bad
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_check_iomb_status(pmcs_hw_t *pwp, uint32_t *iomb)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint16_t opcode;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int offset;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (iomb == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh opcode = LE_32(iomb[0]) & 0xfff;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (opcode) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The following have no status field, so ignore them
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_ECHO:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_SAS_HW_EVENT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_GET_DEVICE_HANDLE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_SATA_EVENT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_SSP_EVENT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_DEVICE_HANDLE_ARRIVED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_SMP_REQUEST_RECEIVED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_GPIO:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_GPIO_EVENT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_GET_TIME_STAMP:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_SKIP_ENTRIES:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_GET_NVMD_DATA: /* Actually lower 16 bits of word 3 */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_SET_NVMD_DATA: /* but ignore - we don't use these */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_DEVICE_HANDLE_REMOVED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_SSP_REQUEST_RECEIVED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_GENERAL_EVENT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh offset = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_SSP_COMPLETION:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_SMP_COMPLETION:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_DEVICE_REGISTRATION:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_DEREGISTER_DEVICE_HANDLE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_SATA_COMPLETION:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_DEVICE_INFO:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_FW_FLASH_UPDATE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_SSP_ABORT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_SATA_ABORT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_SAS_DIAG_MODE_START_END:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_SAS_HW_EVENT_ACK_ACK:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_SMP_ABORT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_SET_DEVICE_STATE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_GET_DEVICE_STATE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_SET_DEVICE_INFO:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh offset = 2;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_LOCAL_PHY_CONTROL:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_SAS_DIAG_EXECUTE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_PORT_CONTROL:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh offset = 3;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_GET_INFO:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_GET_VPD:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_SAS_ASSISTED_DISCOVERY_EVENT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_SATA_ASSISTED_DISCOVERY_EVENT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_SET_VPD:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_TWI:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_print_entry(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Got response for deprecated opcode", iomb);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_print_entry(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Got response for unknown opcode", iomb);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (LE_32(iomb[offset]) != PMCOUT_STATUS_OK) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_print_entry(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "bad status on TAG_TYPE_NONE command", iomb);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with statlock held
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_clear_xp(pmcs_hw_t *pwp, pmcs_xscsi_t *xp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh _NOTE(ARGUNUSED(pwp));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&xp->statlock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: Device 0x%p is gone.", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)xp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler * Clear the dip now. This keeps pmcs_remove_device from attempting
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * to call us on the same device while we're still flushing queues.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The only side effect is we can no longer update SM-HBA properties,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * but this device is going away anyway, so no matter.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->dip = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->special_running = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->recovering = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->recover_wait = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->draining = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->new = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->assigned = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->dev_state = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->tagmap = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->dev_gone = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->event_recovery = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->dtype = NOTHING;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->wq_recovery_tail = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Don't clear xp->phy */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Don't clear xp->actv_cnt */
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler /*
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler * Flush all target queues
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler */
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler pmcs_flush_target_queues(pwp, xp, PMCS_TGT_ALL_QUEUES);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_smp_function_result(pmcs_hw_t *pwp, smp_response_frame_t *srf)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int result = srf->srf_result;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (result) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SMP_RES_UNKNOWN_FUNCTION:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: SMP DISCOVER Response "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Function Result: Unknown SMP Function(0x%x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SMP_RES_FUNCTION_FAILED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: SMP DISCOVER Response "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Function Result: SMP Function Failed(0x%x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SMP_RES_INVALID_REQUEST_FRAME_LENGTH:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: SMP DISCOVER Response "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Function Result: Invalid Request Frame Length(0x%x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SMP_RES_INCOMPLETE_DESCRIPTOR_LIST:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: SMP DISCOVER Response "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Function Result: Incomplete Descriptor List(0x%x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SMP_RES_PHY_DOES_NOT_EXIST:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: SMP DISCOVER Response "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Function Result: PHY does not exist(0x%x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SMP_RES_PHY_VACANT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: SMP DISCOVER Response "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Function Result: PHY Vacant(0x%x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: SMP DISCOVER Response "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Function Result: (0x%x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Do all the repetitive stuff necessary to setup for DMA
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * pwp: Used for dip
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * dma_attr: ddi_dma_attr_t to use for the mapping
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * acch: ddi_acc_handle_t to use for the mapping
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * dmah: ddi_dma_handle_t to use
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * length: Amount of memory for mapping
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * kvp: Pointer filled in with kernel virtual address on successful return
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * dma_addr: Pointer filled in with DMA address on successful return
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhboolean_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_dma_setup(pmcs_hw_t *pwp, ddi_dma_attr_t *dma_attr, ddi_acc_handle_t *acch,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_dma_handle_t *dmah, size_t length, caddr_t *kvp, uint64_t *dma_addr)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh dev_info_t *dip = pwp->dip;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_dma_cookie_t cookie;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh size_t real_length;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint_t ddma_flag = DDI_DMA_CONSISTENT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint_t ddabh_flag = DDI_DMA_CONSISTENT | DDI_DMA_RDWR;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint_t cookie_cnt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_device_acc_attr_t mattr = {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_DEVICE_ATTR_V0,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_NEVERSWAP_ACC,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_STRICTORDER_ACC,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_DEFAULT_ACC
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh };
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *acch = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *dmah = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_dma_alloc_handle(dip, dma_attr, DDI_DMA_SLEEP, NULL, dmah) !=
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "Failed to allocate DMA handle");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_dma_mem_alloc(*dmah, length, &mattr, ddma_flag, DDI_DMA_SLEEP,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh NULL, kvp, &real_length, acch) != DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "Failed to allocate DMA mem");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_dma_free_handle(dmah);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *dmah = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_dma_addr_bind_handle(*dmah, NULL, *kvp, real_length,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddabh_flag, DDI_DMA_SLEEP, NULL, &cookie, &cookie_cnt)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh != DDI_DMA_MAPPED) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "Failed to bind DMA");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_dma_free_handle(dmah);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_dma_mem_free(acch);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *dmah = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *acch = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (cookie_cnt != 1) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "Multiple cookies");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_dma_unbind_handle(*dmah) != DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "Condition failed at "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s():%d", __func__, __LINE__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_dma_free_handle(dmah);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_dma_mem_free(acch);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *dmah = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *acch = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *dma_addr = cookie.dmac_laddress;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Flush requested queues for a particular target. Called with statlock held
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_flush_target_queues(pmcs_hw_t *pwp, pmcs_xscsi_t *tgt, uint8_t queues)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_cmd_t *sp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcwork_t *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pwp != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(tgt != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Flushing queues (%d) for target 0x%p", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh queues, (void *)tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Commands on the wait queue (or the special queue below) don't have
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * work structures associated with them.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (queues & PMCS_TGT_WAIT_QUEUE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&tgt->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while ((sp = STAILQ_FIRST(&tgt->wq)) != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_REMOVE(&tgt->wq, sp, pmcs_cmd, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG1,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Removing cmd 0x%p from wq for target 0x%p",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)sp, (void *)tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CMD2PKT(sp)->pkt_reason = CMD_DEV_GONE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CMD2PKT(sp)->pkt_state = STATE_GOT_BUS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dma_unload(pwp, sp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_TAIL(&pwp->cq, sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&tgt->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Commands on the active queue will have work structures associated
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * with them.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (queues & PMCS_TGT_ACTIVE_QUEUE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&tgt->aqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while ((sp = STAILQ_FIRST(&tgt->aq)) != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_REMOVE(&tgt->aq, sp, pmcs_cmd, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk = pmcs_tag2wp(pwp, sp->cmd_tag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->aqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we found a work structure, mark it as dead
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * and complete it
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk != NULL) {
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 }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG1,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Removing cmd 0x%p from aq for target 0x%p",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)sp, (void *)tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dma_unload(pwp, sp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_TAIL(&pwp->cq, sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&tgt->aqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->aqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (queues & PMCS_TGT_SPECIAL_QUEUE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while ((sp = STAILQ_FIRST(&tgt->sq)) != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_REMOVE(&tgt->sq, sp, pmcs_cmd, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG1,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Removing cmd 0x%p from sq for target 0x%p",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)sp, (void *)tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CMD2PKT(sp)->pkt_reason = CMD_DEV_GONE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CMD2PKT(sp)->pkt_state = STATE_GOT_BUS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dma_unload(pwp, sp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_TAIL(&pwp->cq, sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_complete_work_impl(pmcs_hw_t *pwp, pmcwork_t *pwrk, uint32_t *iomb,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh size_t amt)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (PMCS_TAG_TYPE(pwrk->htag)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_TAG_TYPE_CBACK:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_cb_t callback = (pmcs_cb_t)pwrk->ptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (*callback)(pwp, pwrk, iomb);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_TAG_TYPE_WAIT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk->arg && iomb && amt) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(pwrk->arg, iomb, amt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_signal(&pwrk->sleep_cv);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_TAG_TYPE_NONE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#ifdef DEBUG
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_check_iomb_status(pwp, iomb);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#endif
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We will leak a structure here if we don't know
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * what happened
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: Unknown PMCS_TAG_TYPE (%x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, PMCS_TAG_TYPE(pwrk->htag));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Determine if iport still has targets. During detach(9E), if SCSA is
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * successfull in its guarantee of tran_tgt_free(9E) before detach(9E),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * this should always return B_FALSE.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhboolean_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_iport_has_targets(pmcs_hw_t *pwp, pmcs_iport_t *iport)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *xp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int i;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!pwp->targets || !pwp->max_dev) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < pwp->max_dev; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp = pwp->targets[i];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((xp == NULL) || (xp->phy == NULL) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (xp->phy->iport != iport)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with softstate lock held
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_destroy_target(pmcs_xscsi_t *target)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = target->pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_iport_t *iport;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&pwp->lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!target->ua) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: target %p iport addres is null",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)target);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport = pmcs_get_iport_by_ua(pwp, target->ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (iport == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: no iport associated with tgt(0x%p)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)target);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: free target %p", __func__, (void *)target);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (target->ua) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh strfree(target->ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_destroy(&target->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_destroy(&target->aqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_destroy(&target->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_destroy(&target->reset_cv);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_destroy(&target->abort_cv);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_bystr_fini(&target->lun_sstate);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_bystr_free(iport->tgt_sstate, target->unit_address);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rele_iport(iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Get device state. Called with statlock and PHY lock held.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_get_dev_state(pmcs_hw_t *pwp, pmcs_xscsi_t *xp, uint8_t *ds)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t htag, *ptr, msg[PMCS_MSG_SIZE];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int result;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct pmcwork *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *phyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG3, "%s: tgt(0x%p)", __func__, (void *)xp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: Target is NULL", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&xp->statlock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = xp->phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&phyp->phy_lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nowrk, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->arg = msg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->dtype = phyp->dtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp->valid_device_id == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: Invalid DeviceID", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh htag = pwrk->htag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCIN_GET_DEVICE_STATE));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[2] = LE_32(phyp->device_id);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ptr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nomsg, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh COPY_MESSAGE(ptr, msg, PMCS_MSG_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh WAIT_FOR(pwrk, 1000, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_timed_out(pwp, htag, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: cmd timed out, returning ",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (LE_32(msg[2]) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *ds = (uint8_t)(LE_32(msg[4]));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (*ds != xp->dev_state) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: retrieved_ds=0x%x, target_ds=0x%x", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *ds, xp->dev_state);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: cmd failed Status(0x%x), returning ", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh LE_32(msg[2]));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Set device state. Called with target's statlock and PHY lock held.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_set_dev_state(pmcs_hw_t *pwp, pmcs_xscsi_t *xp, uint8_t ds)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t htag, *ptr, msg[PMCS_MSG_SIZE];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int result;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t pds, nds;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct pmcwork *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *phyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, "%s: ds(0x%x), tgt(0x%p)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, ds, (void *)xp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: Target is Null", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = xp->phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nowrk, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, "%s: PHY is Null",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp->valid_device_id == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Invalid DeviceID", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->arg = msg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->dtype = phyp->dtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh htag = pwrk->htag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCIN_SET_DEVICE_STATE));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[2] = LE_32(phyp->device_id);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[3] = LE_32(ds);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ptr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_ERR, pmcs_nomsg, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh COPY_MESSAGE(ptr, msg, PMCS_MSG_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh WAIT_FOR(pwrk, 1000, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_timed_out(pwp, htag, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: cmd timed out, returning", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (LE_32(msg[2]) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pds = (uint8_t)(LE_32(msg[4]) >> 4);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh nds = (uint8_t)(LE_32(msg[4]) & 0x0000000f);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, "%s: previous_ds=0x%x, "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "new_ds=0x%x", __func__, pds, nds);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->dev_state = nds;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: cmd failed Status(0x%x), returning ", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh LE_32(msg[2]));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_dev_state_recovery(pmcs_hw_t *pwp, pmcs_phy_t *phyp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t ds;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int rc;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *tgt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr, *pnext, *pchild;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * First time, check to see if we're already performing recovery
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->ds_err_recovering) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_DS_ERR_RECOVERY);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->ds_err_recovering = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pwp->root_phys;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = phyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (pptr) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Since ds_err_recovering is set, we can be assured these
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * PHYs won't disappear on us while we do this.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pchild = pptr->children;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pnext = pptr->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pchild) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dev_state_recovery(pwp, pchild);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->dead) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt = pptr->target;
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler if (tgt == NULL || tgt->dev_gone) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->dtype != NOTHING) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG2,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: no target for DS error recovery for "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "PHY 0x%p", __func__, (void *)pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt->recover_wait == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 1: Put the device into the IN_RECOVERY state
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rc = pmcs_get_dev_state(pwp, tgt, &ds);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rc != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: pmcs_get_dev_state on PHY %s "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "failed (rc=%d)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path, rc);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_handle_ds_recovery_error(pptr, tgt, pwp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, __LINE__, "pmcs_get_dev_state");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt->dev_state == ds) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Target 0x%p already IN_RECOVERY", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->dev_state = ds;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ds = PMCS_DEVICE_STATE_IN_RECOVERY;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rc = pmcs_send_err_recovery_cmd(pwp, ds, tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: pmcs_send_err_recovery_cmd "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "result(%d) tgt(0x%p) ds(0x%x) tgt->ds(0x%x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, rc, (void *)tgt, ds, tgt->dev_state);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rc) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: pmcs_send_err_recovery_cmd to PHY %s "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "failed (rc=%d)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path, rc);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_handle_ds_recovery_error(pptr, tgt, pwp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, __LINE__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "pmcs_send_err_recovery_cmd");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 2: Perform a hard reset on the PHY
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Issue HARD_RESET to PHY %s", __func__, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Must release statlock here because pmcs_reset_phy will
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * drop and reacquire the PHY lock.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rc = pmcs_reset_phy(pwp, pptr, PMCS_PHYOP_HARD_RESET);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rc) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: HARD_RESET to PHY %s failed (rc=%d)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path, rc);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_handle_ds_recovery_error(pptr, tgt, pwp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, __LINE__, "HARD_RESET");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 3: Abort all I/Os to the device
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->abort_all_start) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (pptr->abort_all_start) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Waiting for outstanding ABORT_ALL on "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "PHY 0x%p", __func__, (void *)pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_wait(&pptr->abort_all_cv, &pptr->phy_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rc = pmcs_abort(pwp, pptr, pptr->device_id, 1, 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rc != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->abort_pending = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: pmcs_abort to PHY %s failed (rc=%d)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path, rc);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_handle_ds_recovery_error(pptr, tgt,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp, __func__, __LINE__, "pmcs_abort");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Step 4: Set the device back to OPERATIONAL state
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Set PHY/tgt 0x%p/0x%p to OPERATIONAL state",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)pptr, (void *)tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rc = pmcs_set_dev_state(pwp, tgt,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_DEVICE_STATE_OPERATIONAL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rc == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->recover_wait = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->ds_recovery_retries = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Don't bother to run the work queues if the PHY
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * is dead.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt->phy && !tgt->phy->dead) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) ddi_taskq_dispatch(pwp->tq, pmcs_worker,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp, DDI_NOSLEEP);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Failed to SET tgt 0x%p to OPERATIONAL state",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_handle_ds_recovery_error(pptr, tgt, pwp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, __LINE__, "SET tgt to OPERATIONAL state");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhnext_phy:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pnext;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Only clear ds_err_recovering if we're exiting for good and not
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * just unwinding from recursion
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->ds_err_recovering = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with target's statlock and PHY lock held.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_send_err_recovery_cmd(pmcs_hw_t *pwp, uint8_t dev_state, pmcs_xscsi_t *tgt)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int rc = -1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(tgt != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&tgt->statlock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt->recovering) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->recovering = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = tgt->phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, "%s: PHY is Null",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&pptr->phy_lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, "%s: ds: 0x%x, tgt ds(0x%x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, dev_state, tgt->dev_state);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (dev_state) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_DEVICE_STATE_IN_RECOVERY:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt->dev_state == PMCS_DEVICE_STATE_IN_RECOVERY) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Target 0x%p already IN_RECOVERY", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rc = 0; /* This is not an error */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto no_action;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rc = pmcs_set_dev_state(pwp, tgt,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_DEVICE_STATE_IN_RECOVERY);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rc != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s(1): Failed to SET tgt(0x%p) to _IN_RECOVERY",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_DEVICE_STATE_OPERATIONAL:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt->dev_state != PMCS_DEVICE_STATE_IN_RECOVERY) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Target 0x%p not ready to go OPERATIONAL",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto no_action;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rc = pmcs_set_dev_state(pwp, tgt,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_DEVICE_STATE_OPERATIONAL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->reset_success = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rc != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s(2): Failed to SET tgt(0x%p) to OPERATIONAL",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->reset_success = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCS_DEVICE_STATE_NON_OPERATIONAL:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PHY_CHANGED(pwp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh RESTART_DISCOVERY(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Device at %s is non-operational",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->dev_state = PMCS_DEVICE_STATE_NON_OPERATIONAL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rc = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Invalid state requested (%d)", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh dev_state);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhno_action:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->recovering = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (rc);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * pmcs_lock_phy_impl
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This function is what does the actual work for pmcs_lock_phy. It will
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * lock all PHYs from phyp down in a top-down fashion.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Locking notes:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * 1. level starts from 0 for the PHY ("parent") that's passed in. It is
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * not a reflection of the actual level of the PHY in the SAS topology.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * 2. If parent is an expander, then parent is locked along with all its
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * descendents.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * 3. Expander subsidiary PHYs at level 0 are not locked. It is the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * responsibility of the caller to individually lock expander subsidiary PHYs
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * at level 0 if necessary.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * 4. Siblings at level 0 are not traversed due to the possibility that we're
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * locking a PHY on the dead list. The siblings could be pointing to invalid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * PHYs. We don't lock siblings at level 0 anyway.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_lock_phy_impl(pmcs_phy_t *phyp, int level)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *tphyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT((phyp->dtype == SAS) || (phyp->dtype == SATA) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (phyp->dtype == EXPANDER) || (phyp->dtype == NOTHING));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Start walking the PHYs.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tphyp = phyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (tphyp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we're at the top level, only lock ourselves. For anything
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * at level > 0, traverse children while locking everything.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((level > 0) || (tphyp == phyp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(tphyp->pwp, PMCS_PRT_DEBUG_PHY_LOCKING,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: PHY 0x%p parent 0x%p path %s lvl %d",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)tphyp, (void *)tphyp->parent,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tphyp->path, level);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&tphyp->phy_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tphyp->children) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy_impl(tphyp->children, level + 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (level == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tphyp = tphyp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * pmcs_lock_phy
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This function is responsible for locking a PHY and all its descendents
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_lock_phy(pmcs_phy_t *phyp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#ifdef DEBUG
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char *callername = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ulong_t off;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(phyp != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh callername = modgetsymname((uintptr_t)caller(), &off);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (callername == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(phyp->pwp, PMCS_PRT_DEBUG_PHY_LOCKING,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: PHY 0x%p path %s caller: unknown", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)phyp, phyp->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(phyp->pwp, PMCS_PRT_DEBUG_PHY_LOCKING,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: PHY 0x%p path %s caller: %s+%lx", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)phyp, phyp->path, callername, off);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#else
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(phyp->pwp, PMCS_PRT_DEBUG_PHY_LOCKING,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: PHY 0x%p path %s", __func__, (void *)phyp, phyp->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#endif
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy_impl(phyp, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * pmcs_unlock_phy_impl
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Unlock all PHYs from phyp down in a bottom-up fashion.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_unlock_phy_impl(pmcs_phy_t *phyp, int level)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *phy_next;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT((phyp->dtype == SAS) || (phyp->dtype == SATA) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (phyp->dtype == EXPANDER) || (phyp->dtype == NOTHING));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Recurse down to the bottom PHYs
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (level == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp->children) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy_impl(phyp->children, level + 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phy_next = phyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (phy_next) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phy_next->children) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy_impl(phy_next->children,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh level + 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phy_next = phy_next->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Iterate through PHYs unlocking all at level > 0 as well the top PHY
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phy_next = phyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (phy_next) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((level > 0) || (phy_next == phyp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(phy_next->pwp, PMCS_PRT_DEBUG_PHY_LOCKING,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: PHY 0x%p parent 0x%p path %s lvl %d",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)phy_next,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)phy_next->parent, phy_next->path, level);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&phy_next->phy_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (level == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phy_next = phy_next->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * pmcs_unlock_phy
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Unlock a PHY and all its descendents
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_unlock_phy(pmcs_phy_t *phyp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#ifdef DEBUG
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char *callername = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ulong_t off;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(phyp != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh callername = modgetsymname((uintptr_t)caller(), &off);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (callername == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(phyp->pwp, PMCS_PRT_DEBUG_PHY_LOCKING,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: PHY 0x%p path %s caller: unknown", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)phyp, phyp->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(phyp->pwp, PMCS_PRT_DEBUG_PHY_LOCKING,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: PHY 0x%p path %s caller: %s+%lx", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)phyp, phyp->path, callername, off);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#else
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(phyp->pwp, PMCS_PRT_DEBUG_PHY_LOCKING,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: PHY 0x%p path %s", __func__, (void *)phyp, phyp->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#endif
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy_impl(phyp, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * pmcs_get_root_phy
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * For a given phy pointer return its root phy.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The caller must be holding the lock on every PHY from phyp up to the root.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_phy_t *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_get_root_phy(pmcs_phy_t *phyp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (phyp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (IS_ROOT_PHY(phyp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = phyp->parent;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * pmcs_free_dma_chunklist
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Free DMA S/G chunk list
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_free_dma_chunklist(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_chunk_t *pchunk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (pwp->dma_chunklist) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pchunk = pwp->dma_chunklist;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->dma_chunklist = pwp->dma_chunklist->next;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pchunk->dma_handle) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_dma_unbind_handle(pchunk->dma_handle) !=
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "Condition failed"
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh " at %s():%d", __func__, __LINE__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_dma_free_handle(&pchunk->dma_handle);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_dma_mem_free(&pchunk->acc_handle);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_free(pchunk, sizeof (pmcs_chunk_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Start ssp event recovery. We have to schedule recovery operation because
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * it involves sending multiple commands to device and we should not do it
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * in the interrupt context.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If it is failure of a recovery command, let the recovery thread deal with it.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with pmcwork lock held.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_start_ssp_event_recovery(pmcs_hw_t *pwp, pmcwork_t *pwrk, uint32_t *iomb,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh size_t amt)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *tgt = pwrk->xp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t event = LE_32(iomb[2]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr = pwrk->phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t tag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&tgt->statlock);
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler if (!tgt->assigned) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dec_phy_ref_count(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->phy = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler * No target, need to run RE-DISCOVERY here.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk->state != PMCS_WORK_STATE_TIMED_OUT) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_INTR;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Although we cannot mark phy to force abort nor mark phy
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * as changed, killing of a target would take care of aborting
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * commands for the device.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: No valid target for event "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "processing found. Scheduling RECONFIGURE", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh RESTART_DISCOVERY(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (event == PMCOUT_STATUS_OPEN_CNX_ERROR_IT_NEXUS_LOSS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt->dev_state !=
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_DEVICE_STATE_NON_OPERATIONAL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: Device at "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s is non-operational", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->dev_state =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_DEVICE_STATE_NON_OPERATIONAL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->abort_pending = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh RESTART_DISCOVERY(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If this command is run in WAIT mode, it is a failing recovery
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * command. If so, just wake up recovery thread waiting for
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * command completion.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tag = PMCS_TAG_TYPE(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tag == PMCS_TAG_TYPE_WAIT) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->htag |= PMCS_TAG_DONE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk->arg && amt) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(pwrk->arg, iomb, amt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_signal(&pwrk->sleep_cv);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * To recover from primary failures,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * we need to schedule handling events recovery.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->event_recovery = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->ssp_event = event;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Scheduling SSP event recovery for tgt(0x%p) "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "pwrk(%p) tag(0x%x)", __func__, (void *)tgt, (void *)pwrk,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_SSP_EVT_RECOVERY);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Work cannot be completed until event recovery is completed. */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * SSP target event recovery
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Entered with a phy lock held
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Pwrk lock is not needed - pwrk is on the target aq and no other thread
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * will do anything with it until this thread starts the chain of recovery.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Statlock may be acquired and released.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_tgt_event_recovery(pmcs_hw_t *pwp, pmcwork_t *pwrk)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr = pwrk->phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_cmd_t *sp = pwrk->arg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lun_t *lun = sp->cmd_lun;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *tgt = pwrk->xp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t event;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t htag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t status;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t dstate;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int rv;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pwrk->arg != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pwrk->xp != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG, "%s: event recovery for "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "target 0x%p", __func__, (void *)pwrk->xp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh htag = pwrk->htag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh event = pwrk->ssp_event;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->ssp_event = 0xffffffff;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (event == PMCOUT_STATUS_XFER_ERR_BREAK ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh event == PMCOUT_STATUS_XFER_ERR_PHY_NOT_READY ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh event == PMCOUT_STATUS_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Command may be still pending on device */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rv = pmcs_ssp_tmf(pwp, pptr, SAS_QUERY_TASK, htag,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh lun->lun_num, &status);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rv != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (status == SAS_RSP_TMF_COMPLETE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Command NOT pending on a device */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: No pending command for tgt 0x%p",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Nothing more to do, just abort it on chip */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh htag = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * All other events left the command pending in the host
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Send abort task and abort it on the chip
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (htag != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_ssp_tmf(pwp, pptr, SAS_ABORT_TASK, htag,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh lun->lun_num, &status))
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_abort(pwp, pptr, pwrk->htag, 0, 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Abort either took care of work completion, or put device in
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * a recovery state
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhout:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Abort failed, do full device recovery */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!pmcs_get_dev_state(pwp, tgt, &dstate))
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->dev_state = dstate;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((tgt->dev_state != PMCS_DEVICE_STATE_IN_RECOVERY) &&
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (tgt->dev_state != PMCS_DEVICE_STATE_NON_OPERATIONAL)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Setting IN_RECOVERY for tgt 0x%p",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_send_err_recovery_cmd(pwp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_DEVICE_STATE_IN_RECOVERY, tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * SSP event recovery task.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_ssp_event_recovery(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int idx;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *tgt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_cmd_t *cp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcwork_t *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pphy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int er_flag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t idxpwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhrestart:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (idx = 0; idx < pwp->max_dev; idx++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt = pwp->targets[idx];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&tgt->statlock);
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler if (!tgt->assigned) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pphy = tgt->phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh er_flag = tgt->event_recovery;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pphy != NULL && er_flag != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pphy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: found target(0x%p)", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *) tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Check what cmd expects recovery */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&tgt->aqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_FOREACH(cp, &tgt->aq, cmd_next) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Since work structure is on this
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * target aq, and only this thread
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * is accessing it now, we do not need
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * to lock it
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh idxpwrk = PMCS_TAG_INDEX(cp->cmd_tag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk = &pwp->work[idxpwrk];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk->htag != cp->cmd_tag) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * aq may contain TMF commands,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * so we may not find work
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * structure with htag
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk->ssp_event != 0 &&
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->ssp_event !=
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_REC_EVENT) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: pwrk(%p) ctag(0x%x)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *) pwrk,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cp->cmd_tag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->aqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_tgt_event_recovery(
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We dropped statlock, so
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * restart scanning from scratch
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pphy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto restart;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->aqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->event_recovery = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: end of SSP event recovery for "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "target(0x%p)", __func__, (void *) tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pphy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: end of SSP event recovery for pwp(0x%p)", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *) pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*ARGSUSED2*/
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_phy_constructor(void *buf, void *arg, int kmflags)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = (pmcs_hw_t *)arg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *phyp = (pmcs_phy_t *)buf;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&phyp->phy_lock, NULL, MUTEX_DRIVER,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_INTR_PRI(pwp->intr_pri));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_init(&phyp->abort_all_cv, NULL, CV_DRIVER, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*ARGSUSED1*/
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_phy_destructor(void *buf, void *arg)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *phyp = (pmcs_phy_t *)buf;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_destroy(&phyp->abort_all_cv);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_destroy(&phyp->phy_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Free all PHYs from the kmem_cache starting at phyp as well as everything
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * on the dead_phys list.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * NOTE: This function does not free root PHYs as they are not allocated
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * from the kmem_cache.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * No PHY locks are acquired as this should only be called during DDI_DETACH
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * or soft reset (while pmcs interrupts are disabled).
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_free_all_phys(pmcs_hw_t *pwp, pmcs_phy_t *phyp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *tphyp, *nphyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tphyp = phyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (tphyp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh nphyp = tphyp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tphyp->children) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_free_all_phys(pwp, tphyp->children);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tphyp->children = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!IS_ROOT_PHY(tphyp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_cache_free(pwp->phy_cache, tphyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tphyp = nphyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tphyp = pwp->dead_phys;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (tphyp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh nphyp = tphyp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_cache_free(pwp->phy_cache, tphyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tphyp = nphyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->dead_phys = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Free a list of PHYs linked together by the sibling pointer back to the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * kmem cache from whence they came. This function does not recurse, so the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * caller must ensure there are no children.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_free_phys(pmcs_hw_t *pwp, pmcs_phy_t *phyp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (phyp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh next_phy = phyp->sibling;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(!mutex_owned(&phyp->phy_lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_cache_free(pwp->phy_cache, phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = next_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Make a copy of an existing PHY structure. This is used primarily in
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * discovery to compare the contents of an existing PHY with what gets
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * reported back by an expander.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This function must not be called from any context where sleeping is
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * not possible.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The new PHY is returned unlocked.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic pmcs_phy_t *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_clone_phy(pmcs_phy_t *orig_phy)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *local;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh local = kmem_cache_alloc(orig_phy->pwp->phy_cache, KM_SLEEP);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Go ahead and just copy everything...
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *local = *orig_phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * But the following must be set appropriately for this copy
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh local->sibling = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh local->children = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&local->phy_lock, NULL, MUTEX_DRIVER,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_INTR_PRI(orig_phy->pwp->intr_pri));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (local);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_check_acc_handle(ddi_acc_handle_t handle)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_fm_error_t de;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (handle == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_fm_acc_err_get(handle, &de, DDI_FME_VER0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (de.fme_status);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_check_dma_handle(ddi_dma_handle_t handle)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_fm_error_t de;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (handle == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_fm_dma_err_get(handle, &de, DDI_FME_VER0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (de.fme_status);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_fm_ereport(pmcs_hw_t *pwp, char *detail)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint64_t ena;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char buf[FM_MAX_CLASS];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(buf, FM_MAX_CLASS, "%s.%s", DDI_FM_DEVICE, detail);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ena = fm_ena_generate(0, FM_ENA_FMT1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (DDI_FM_EREPORT_CAP(pwp->fm_capabilities)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_fm_ereport_post(pwp->dip, buf, ena, DDI_NOSLEEP,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh FM_VERSION, DATA_TYPE_UINT8, FM_EREPORT_VERS0, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_check_acc_dma_handle(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_chunk_t *pchunk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int i;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* check all acc & dma handles allocated in attach */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((pmcs_check_acc_handle(pwp->pci_acc_handle) != DDI_SUCCESS) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pmcs_check_acc_handle(pwp->msg_acc_handle) != DDI_SUCCESS) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pmcs_check_acc_handle(pwp->top_acc_handle) != DDI_SUCCESS) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pmcs_check_acc_handle(pwp->mpi_acc_handle) != DDI_SUCCESS) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pmcs_check_acc_handle(pwp->gsm_acc_handle) != DDI_SUCCESS)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto check_failed;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < PMCS_NIQ; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((pmcs_check_dma_handle(
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->iqp_handles[i]) != DDI_SUCCESS) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pmcs_check_acc_handle(
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->iqp_acchdls[i]) != DDI_SUCCESS)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto check_failed;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < PMCS_NOQ; i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((pmcs_check_dma_handle(
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->oqp_handles[i]) != DDI_SUCCESS) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pmcs_check_acc_handle(
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->oqp_acchdls[i]) != DDI_SUCCESS)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto check_failed;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((pmcs_check_dma_handle(pwp->cip_handles) != DDI_SUCCESS) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pmcs_check_acc_handle(pwp->cip_acchdls) != DDI_SUCCESS)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto check_failed;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->fwlog &&
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ((pmcs_check_dma_handle(pwp->fwlog_hndl) != DDI_SUCCESS) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pmcs_check_acc_handle(pwp->fwlog_acchdl) != DDI_SUCCESS))) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto check_failed;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->regdump_hndl && pwp->regdump_acchdl &&
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ((pmcs_check_dma_handle(pwp->regdump_hndl) != DDI_SUCCESS) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pmcs_check_acc_handle(pwp->regdump_acchdl)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh != DDI_SUCCESS))) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto check_failed;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pchunk = pwp->dma_chunklist;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (pchunk) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((pmcs_check_acc_handle(pchunk->acc_handle)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh != DDI_SUCCESS) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pmcs_check_dma_handle(pchunk->dma_handle)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh != DDI_SUCCESS)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto check_failed;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pchunk = pchunk->next;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhcheck_failed:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * pmcs_handle_dead_phys
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the PHY has no outstanding work associated with it, remove it from
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the dead PHY list and free it.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If pwp->ds_err_recovering or pwp->configuring is set, don't run.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This keeps routines that need to submit work to the chip from having to
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * hold PHY locks to ensure that PHYs don't disappear while they do their work.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_handle_dead_phys(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *phyp, *nphyp, *pphyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->configuring | pwp->ds_err_recovering) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Check every PHY in the dead PHY list
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->dead_phylist_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = pwp->dead_phys;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pphyp = NULL; /* Set previous PHY to NULL */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (phyp != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(phyp->dead);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh nphyp = phyp->dead_next;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Check for outstanding work
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp->ref_count > 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pphyp = phyp; /* This PHY becomes "previous" */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (phyp->target) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG1,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Not freeing PHY 0x%p: target 0x%p is not free",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)phyp, (void *)phyp->target);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pphyp = phyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * No outstanding work or target references. Remove it
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * from the list and free it
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Freeing inactive dead PHY 0x%p @ %s "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "target = 0x%p", __func__, (void *)phyp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp->path, (void *)phyp->target);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If pphyp is NULL, then phyp was the head of the list,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * so just reset the head to nphyp. Otherwise, the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * previous PHY will now point to nphyp (the next PHY)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pphyp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->dead_phys = nphyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pphyp->dead_next = nphyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the target still points to this PHY, remove
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * that linkage now.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp->target) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&phyp->target->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp->target->phy == phyp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp->target->phy = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&phyp->target->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_cache_free(pwp->phy_cache, phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = nphyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->dead_phylist_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->config_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_inc_phy_ref_count(pmcs_phy_t *phyp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh atomic_inc_32(&phyp->ref_count);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_dec_phy_ref_count(pmcs_phy_t *phyp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(phyp->ref_count != 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh atomic_dec_32(&phyp->ref_count);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * pmcs_reap_dead_phy
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This function is called from pmcs_new_tport when we have a PHY
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * without a target pointer. It's possible in that case that this PHY
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * may have a "brother" on the dead_phys list. That is, it may be the same as
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * this one but with a different root PHY number (e.g. pp05 vs. pp04). If
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * that's the case, update the dead PHY and this new PHY. If that's not the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * case, we should get a tran_tgt_init on this after it's reported to SCSA.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with PHY locked.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_reap_dead_phy(pmcs_phy_t *phyp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = phyp->pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *ctmp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&phyp->phy_lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Check the dead PHYs list
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->dead_phylist_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = pwp->dead_phys;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (ctmp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((ctmp->iport != phyp->iport) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (memcmp((void *)&ctmp->sas_address[0],
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)&phyp->sas_address[0], 8))) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = ctmp->dead_next;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Same SAS address on same iport. Now check to see if
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the PHY path is the same with the possible exception
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * of the root PHY number.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The "5" is the string length of "pp00."
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((strnlen(phyp->path, 5) >= 5) &&
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (strnlen(ctmp->path, 5) >= 5)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (memcmp((void *)&phyp->path[5],
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)&ctmp->path[5],
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh strnlen(phyp->path, 32) - 5) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp = ctmp->dead_next;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->dead_phylist_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Found a match. Remove the target linkage and drop the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * ref count on the old PHY. Then, increment the ref count
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * on the new PHY to compensate.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ctmp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Found match in dead PHY list for new PHY %s",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, phyp->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ctmp->target) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If there is a pointer to the target in the dead
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * PHY, and that PHY's ref_count drops to 0, we can
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * clear the target linkage now. If the PHY's
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * ref_count is > 1, then there may be multiple
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * LUNs still remaining, so leave the linkage.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_inc_phy_ref_count(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dec_phy_ref_count(ctmp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp->target = ctmp->target;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Update the target's linkage as well
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&phyp->target->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp->target->phy = phyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp->target->dtype = phyp->dtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&phyp->target->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ctmp->ref_count == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ctmp->target = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with iport lock held
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_add_phy_to_iport(pmcs_iport_t *iport, pmcs_phy_t *phyp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&iport->lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(!list_link_active(&phyp->list_node));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport->nphy++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_smhba_add_iport_prop(iport, DATA_TYPE_INT32, PMCS_NUM_PHYS,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &iport->nphy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh list_insert_tail(&iport->phys, phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&iport->refcnt_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport->refcnt++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&iport->refcnt_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with the iport lock held
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_remove_phy_from_iport(pmcs_iport_t *iport, pmcs_phy_t *phyp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr, *next_pptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&iport->lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If phyp is NULL, remove all PHYs from the iport
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (pptr = list_head(&iport->phys); pptr != NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = next_pptr) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh next_pptr = list_next(&iport->phys, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pptr->phy_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->iport = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pptr->phy_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rele_iport(iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh list_remove(&iport->phys, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport->nphy = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(iport->nphy > 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(list_link_active(&phyp->list_node));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport->nphy--;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_smhba_add_iport_prop(iport, DATA_TYPE_INT32, PMCS_NUM_PHYS,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &iport->nphy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh list_remove(&iport->phys, phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_rele_iport(iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This function checks to see if the target pointed to by phyp is still
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * correct. This is done by comparing the target's unit address with the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * SAS address in phyp.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with PHY locked and target statlock held
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic boolean_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_phy_target_match(pmcs_phy_t *phyp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint64_t wwn;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char unit_address[PMCS_MAX_UA_SIZE];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh boolean_t rval = B_FALSE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(phyp->target);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&phyp->phy_lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&phyp->target->statlock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh wwn = pmcs_barray2wwn(phyp->sas_address);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) scsi_wwn_to_wwnstr(wwn, 1, unit_address);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (memcmp((void *)unit_address, (void *)phyp->target->unit_address,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh strnlen(phyp->target->unit_address, PMCS_MAX_UA_SIZE)) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (rval);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_start_dev_state_recovery(pmcs_xscsi_t *xp, pmcs_phy_t *phyp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&xp->statlock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(xp->pwp != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->recover_wait == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(xp->pwp, PMCS_PRT_DEBUG_DEV_STATE,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Start ds_recovery for tgt 0x%p/PHY 0x%p (%s)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)xp, (void *)phyp, phyp->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->recover_wait = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Rather than waiting for the watchdog timer, we'll
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * kick it right now.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(xp->pwp, PMCS_WORK_DS_ERR_RECOVERY);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) ddi_taskq_dispatch(xp->pwp->tq, pmcs_worker, xp->pwp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_NOSLEEP);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Increment the phy ds error retry count.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If too many retries, mark phy dead and restart discovery;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * otherwise schedule ds recovery.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_handle_ds_recovery_error(pmcs_phy_t *phyp, pmcs_xscsi_t *tgt,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp, const char *func_name, int line, char *reason_string)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&phyp->phy_lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp->ds_recovery_retries++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp->ds_recovery_retries > PMCS_MAX_DS_RECOVERY_RETRIES) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_prt(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: retry limit reached after %s to PHY %s failed",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh func_name, reason_string, phyp->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->recover_wait = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp->dead = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PHY_CHANGED_AT_LOCATION(pwp, phyp, func_name, line);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh RESTART_DISCOVERY(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_DS_ERR_RECOVERY);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}