4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * CDDL HEADER START
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The contents of this file are subject to the terms of the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Common Development and Distribution License (the "License").
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * You may not use this file except in compliance with the License.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * or http://www.opensolaris.org/os/licensing.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * See the License for the specific language governing permissions
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * and limitations under the License.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * When distributing Covered Code, include this CDDL HEADER in each
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If applicable, add the following below this CDDL HEADER, with the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * fields enclosed by brackets "[]" replaced with your own identifying
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * information: Portions Copyright [yyyy] [name of copyright owner]
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * CDDL HEADER END
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister */
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister/*
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * SCSI (SCSA) midlayer interface for PMC drier.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#include <sys/scsi/adapters/pmcs/pmcs.h>
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhextern scsi_lun_t scsi_lun64_to_lun(scsi_lun64_t lun64);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_scsa_tran_tgt_init(dev_info_t *, dev_info_t *,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_hba_tran_t *, struct scsi_device *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void pmcs_scsa_tran_tgt_free(dev_info_t *, dev_info_t *,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_hba_tran_t *, struct scsi_device *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_scsa_start(struct scsi_address *, struct scsi_pkt *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_scsa_abort(struct scsi_address *, struct scsi_pkt *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_scsa_reset(struct scsi_address *, int);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_scsi_reset_notify(struct scsi_address *, int,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh void (*)(caddr_t), caddr_t);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_scsa_getcap(struct scsi_address *, char *, int);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_scsa_setcap(struct scsi_address *, char *, int, int);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_scsa_setup_pkt(struct scsi_pkt *, int (*)(caddr_t), caddr_t);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void pmcs_scsa_teardown_pkt(struct scsi_pkt *);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Hornestatic int pmcs_smp_init(dev_info_t *, dev_info_t *, smp_hba_tran_t *,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh smp_device_t *);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Hornestatic void pmcs_smp_free(dev_info_t *, dev_info_t *, smp_hba_tran_t *,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh smp_device_t *);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Hornestatic int pmcs_smp_start(struct smp_pkt *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_scsi_quiesce(dev_info_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_scsi_unquiesce(dev_info_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_cap(struct scsi_address *, char *, int, int, int);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic pmcs_xscsi_t *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_addr2xp(struct scsi_address *, uint64_t *, pmcs_cmd_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_SAS_run(pmcs_cmd_t *, pmcwork_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void pmcs_SAS_done(pmcs_hw_t *, pmcwork_t *, uint32_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_SATA_run(pmcs_cmd_t *, pmcwork_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void pmcs_SATA_done(pmcs_hw_t *, pmcwork_t *, uint32_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic uint8_t pmcs_SATA_rwparm(uint8_t *, uint32_t *, uint64_t *, uint64_t);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void pmcs_ioerror(pmcs_hw_t *, pmcs_dtype_t pmcs_dtype,
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister pmcwork_t *, uint32_t *, uint32_t);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhint
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsa_init(pmcs_hw_t *pwp, const ddi_dma_attr_t *ap)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_hba_tran_t *tran;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_dma_attr_t pmcs_scsa_dattr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int flags;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(&pmcs_scsa_dattr, ap, sizeof (ddi_dma_attr_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_scsa_dattr.dma_attr_sgllen =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ((PMCS_SGL_NCHUNKS - 1) * (PMCS_MAX_CHUNKS - 1)) + PMCS_SGL_NCHUNKS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_scsa_dattr.dma_attr_flags = DDI_DMA_RELAXED_ORDERING;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_scsa_dattr.dma_attr_flags |= DDI_DMA_FLAGERR;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Allocate a transport structure
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tran = scsi_hba_tran_alloc(pwp->dip, SCSI_HBA_CANSLEEP);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tran == NULL) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "scsi_hba_tran_alloc failed");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tran->tran_hba_private = pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tran->tran_tgt_init = pmcs_scsa_tran_tgt_init;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tran->tran_tgt_free = pmcs_scsa_tran_tgt_free;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tran->tran_start = pmcs_scsa_start;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tran->tran_abort = pmcs_scsa_abort;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tran->tran_reset = pmcs_scsa_reset;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tran->tran_reset_notify = pmcs_scsi_reset_notify;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tran->tran_getcap = pmcs_scsa_getcap;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tran->tran_setcap = pmcs_scsa_setcap;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tran->tran_setup_pkt = pmcs_scsa_setup_pkt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tran->tran_teardown_pkt = pmcs_scsa_teardown_pkt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tran->tran_quiesce = pmcs_scsi_quiesce;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tran->tran_unquiesce = pmcs_scsi_unquiesce;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tran->tran_interconnect_type = INTERCONNECT_SAS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tran->tran_hba_len = sizeof (pmcs_cmd_t);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Attach this instance of the hba
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh flags = SCSI_HBA_TRAN_SCB | SCSI_HBA_TRAN_CDB | SCSI_HBA_ADDR_COMPLEX |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCSI_HBA_TRAN_PHCI | SCSI_HBA_HBA;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (scsi_hba_attach_setup(pwp->dip, &pmcs_scsa_dattr, tran, flags)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_hba_tran_free(tran);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "scsi_hba_attach failed");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->tran = tran;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Attach the SMP part of this hba
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne pwp->smp_tran = smp_hba_tran_alloc(pwp->dip);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pwp->smp_tran != NULL);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne pwp->smp_tran->smp_tran_hba_private = pwp;
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne pwp->smp_tran->smp_tran_init = pmcs_smp_init;
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne pwp->smp_tran->smp_tran_free = pmcs_smp_free;
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne pwp->smp_tran->smp_tran_start = pmcs_smp_start;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne if (smp_hba_attach_setup(pwp->dip, pwp->smp_tran) != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne "smp_hba_attach failed");
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_hba_tran_free(pwp->smp_tran);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->smp_tran = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_hba_tran_free(tran);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * SCSA entry points
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsa_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_hba_tran_t *tran, struct scsi_device *sd)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int rval;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char *variant_prop = "sata";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char *tgt_port = NULL, *ua = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *tgt = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_iport_t *iport;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lun_t *lun = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *phyp = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint64_t lun_num;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh boolean_t got_scratch = B_FALSE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * First, make sure we're an iport and get the pointer to the HBA
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * node's softstate
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (scsi_hba_iport_unit_address(hba_dip) == NULL) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(TRAN2PMC(tran), PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: We don't enumerate devices on the HBA node", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto tgt_init_fail;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp = ITRAN2PMC(tran);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport = ITRAN2IPORT(tran);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed /*
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed * Get the unit-address
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed */
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed ua = scsi_device_unit_address(sd);
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed if (ua == NULL) {
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed "%s: Couldn't get UA", __func__);
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed pwp = NULL;
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed goto tgt_init_fail;
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed }
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed pmcs_prt(pwp, PMCS_PRT_DEBUG3, NULL, NULL,
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed "got ua '%s'", ua);
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Get the target address
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = scsi_device_prop_lookup_string(sd, SCSI_DEVICE_PROP_PATH,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCSI_ADDR_PROP_TARGET_PORT, &tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rval != DDI_PROP_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "Couldn't get target UA");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto tgt_init_fail;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG3, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "got tgt_port '%s'", tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Validate that this tran_tgt_init is for an active iport.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (iport->ua_state == UA_INACTIVE) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Got tran_tgt_init on inactive iport for '%s'",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto tgt_init_fail;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Since we're going to wait for scratch, be sure to acquire it while
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * we're not holding any other locks
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_acquire_scratch(pwp, B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh got_scratch = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * See if there's already a target softstate. If not, allocate one.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler tgt = pmcs_get_target(iport, tgt_port, B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt == NULL) {
188eaed9d5f14c73dfba1cd0dabaa430bdfd4a9aSrikanth Suravajhala pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "%s: "
188eaed9d5f14c73dfba1cd0dabaa430bdfd4a9aSrikanth Suravajhala "No tgt for tgt_port (%s)", __func__, tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto tgt_init_fail;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = tgt->phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!IS_ROOT_PHY(phyp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_inc_phy_ref_count(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&phyp->phy_lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed pmcs_prt(pwp, PMCS_PRT_DEBUG2, phyp, tgt, "@%s tgt = 0x%p, dip = 0x%p",
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed ua, (void *)tgt, (void *)tgt_dip);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed /* Now get the lun */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh lun_num = scsi_device_prop_get_int64(sd, SCSI_DEVICE_PROP_PATH,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCSI_ADDR_PROP_LUN64, SCSI_LUN64_ILLEGAL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (lun_num == SCSI_LUN64_ILLEGAL) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, phyp, tgt,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "No LUN for tgt %p", (void *)tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto tgt_init_fail;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, phyp, tgt, "%s: @%s tgt 0x%p phy "
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "0x%p (%s)", __func__, ua, (void *)tgt, (void *)phyp, phyp->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->dtype = phyp->dtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt->dtype != SAS && tgt->dtype != SATA) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, phyp, tgt,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "PHY 0x%p went away?", (void *)phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto tgt_init_fail;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* We don't support SATA devices at LUN > 0. */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((tgt->dtype == SATA) && (lun_num > 0)) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, phyp, tgt,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: No support for SATA devices at LUN > 0 "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "(target = 0x%p)", __func__, (void *)tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto tgt_init_fail;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Allocate LU soft state. We use ddi_soft_state_bystr_zalloc instead
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * of kmem_alloc because ddi_soft_state_bystr_zalloc allows us to
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * verify that the framework never tries to initialize two scsi_device
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * structures with the same unit-address at the same time.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_soft_state_bystr_zalloc(tgt->lun_sstate, ua) != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG2, phyp, tgt,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Couldn't allocate LU soft state");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto tgt_init_fail;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh lun = ddi_soft_state_bystr_get(tgt->lun_sstate, ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (lun == NULL) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG2, phyp, tgt,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "Couldn't get LU soft state");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto tgt_init_fail;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_device_hba_private_set(sd, lun);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh lun->lun_num = lun_num;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* convert the scsi_lun64_t value to SCSI standard form */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh lun->scsi_lun = scsi_lun64_to_lun(lun_num);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(strlen(ua) < (PMCS_MAX_UA_SIZE - 1));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bcopy(ua, lun->unit_address, strnlen(ua, PMCS_MAX_UA_SIZE - 1));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh lun->target = tgt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If this is the first tran_tgt_init, add this target to our list
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt->target_num == PMCS_INVALID_TARGET_NUM) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int target;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (target = 0; target < pwp->max_dev; target++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->targets[target] != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->targets[target] = tgt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->target_num = (uint16_t)target;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (target == pwp->max_dev) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, phyp, tgt,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Target list full.");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto tgt_init_fail;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->dip = sd->sd_dev;
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister lun->sd = sd;
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister list_insert_tail(&tgt->lun_list, lun);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!pmcs_assign_device(pwp, tgt)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_release_scratch(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->targets[tgt->target_num] = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->target_num = PMCS_INVALID_TARGET_NUM;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->phy = NULL;
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, phyp, tgt,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: pmcs_assign_device failed for target 0x%p",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto tgt_init_fail;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_release_scratch(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->ref_count++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) scsi_device_prop_update_int(sd, SCSI_DEVICE_PROP_PATH,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCSI_ADDR_PROP_TARGET, (uint32_t)(tgt->target_num));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* SM-HBA */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt->dtype == SATA) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* TCR in PSARC/1997/281 opinion */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) scsi_device_prop_update_string(sd,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCSI_DEVICE_PROP_PATH, "variant", variant_prop);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->phy_addressable = PMCS_PHY_ADDRESSABLE(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt->phy_addressable) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) scsi_device_prop_update_int(sd, SCSI_DEVICE_PROP_PATH,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCSI_ADDR_PROP_SATA_PHY, phyp->phynum);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* SM-HBA */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_smhba_set_scsi_device_props(pwp, phyp, sd);
499cfd156ad653fc27397c5f021047c091dd12c5David Hollister /*
499cfd156ad653fc27397c5f021047c091dd12c5David Hollister * Make sure attached port and target port pm props are updated
499cfd156ad653fc27397c5f021047c091dd12c5David Hollister * By passing in 0s, we're not actually updating any values, but
499cfd156ad653fc27397c5f021047c091dd12c5David Hollister * the properties should now get updated on the node.
499cfd156ad653fc27397c5f021047c091dd12c5David Hollister */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->statlock);
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister pmcs_update_phy_pm_props(phyp, 0, 0, B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhtgt_init_fail:
616875b414de63a60e3f732e0d9b5345f07f9221David Hollister scsi_device_hba_private_set(sd, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (got_scratch) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_release_scratch(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (lun) {
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister list_remove(&tgt->lun_list, lun);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_bystr_free(tgt->lun_sstate, ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * phyp's ref count was incremented in pmcs_new_tport.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We're failing configuration, we now need to decrement it.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!IS_ROOT_PHY(phyp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dec_phy_ref_count(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp->target = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt && tgt->ref_count == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_bystr_free(iport->tgt_sstate, tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, phyp, tgt,
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed "%s: failed for @%s tgt 0x%p phy 0x%p", __func__, ua,
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed (void *)tgt, (void *)phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt_port) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsa_tran_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_hba_tran_t *tran, struct scsi_device *sd)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh _NOTE(ARGUNUSED(hba_dip, tgt_dip));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lun_t *lun;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *target;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char *unit_address;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *phyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (scsi_hba_iport_unit_address(hba_dip) == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp = TRAN2PMC(tran);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: We don't enumerate devices on the HBA node", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh lun = (pmcs_lun_t *)scsi_device_hba_private_get(sd);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT((lun != NULL) && (lun->target != NULL));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(lun->target->ref_count > 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh target = lun->target;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh unit_address = lun->unit_address;
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister list_remove(&target->lun_list, lun);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp = ITRAN2PMC(tran);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = target->phy;
ee13933a0bbf5c72c183bd6af13573d82b78856aSrikanth Suravajhala if (phyp) {
ee13933a0bbf5c72c183bd6af13573d82b78856aSrikanth Suravajhala mutex_enter(&phyp->phy_lock);
ee13933a0bbf5c72c183bd6af13573d82b78856aSrikanth Suravajhala }
ee13933a0bbf5c72c183bd6af13573d82b78856aSrikanth Suravajhala mutex_enter(&target->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, phyp, target,
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister "%s: for @%s tgt 0x%p phy 0x%p", __func__, unit_address,
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister (void *)target, (void *)phyp);
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister ddi_soft_state_bystr_free(lun->target->lun_sstate, unit_address);
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister
af68568220d139fee6e01579437e660dbfee20a8Srikanth, Ramana if (target->recover_wait) {
af68568220d139fee6e01579437e660dbfee20a8Srikanth, Ramana mutex_exit(&target->statlock);
ee13933a0bbf5c72c183bd6af13573d82b78856aSrikanth Suravajhala if (phyp) {
ee13933a0bbf5c72c183bd6af13573d82b78856aSrikanth Suravajhala mutex_exit(&phyp->phy_lock);
ee13933a0bbf5c72c183bd6af13573d82b78856aSrikanth Suravajhala }
af68568220d139fee6e01579437e660dbfee20a8Srikanth, Ramana mutex_exit(&pwp->lock);
af68568220d139fee6e01579437e660dbfee20a8Srikanth, Ramana pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, phyp, target, "%s: "
af68568220d139fee6e01579437e660dbfee20a8Srikanth, Ramana "Target 0x%p in device state recovery, fail tran_tgt_free",
af68568220d139fee6e01579437e660dbfee20a8Srikanth, Ramana __func__, (void *)target);
af68568220d139fee6e01579437e660dbfee20a8Srikanth, Ramana return;
af68568220d139fee6e01579437e660dbfee20a8Srikanth, Ramana }
af68568220d139fee6e01579437e660dbfee20a8Srikanth, Ramana
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If this target still has a PHY pointer and that PHY's target pointer
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * has been cleared, then that PHY has been reaped. In that case, there
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * would be no need to decrement the reference count
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp && !IS_ROOT_PHY(phyp) && phyp->target) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dec_phy_ref_count(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (--target->ref_count == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Remove this target from our list. The target soft
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * state will remain, and the device will remain registered
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * with the hardware unless/until we're told the device
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * physically went away.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, phyp, target,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Free target 0x%p (vtgt %d)", __func__, (void *)target,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh target->target_num);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->targets[target->target_num] = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh target->target_num = PMCS_INVALID_TARGET_NUM;
6c87a171a391b9e1c12d8fb7f74466f7e6e637afJesse Butler /* If the PHY has a pointer to this target, clear it */
6c87a171a391b9e1c12d8fb7f74466f7e6e637afJesse Butler if (phyp && (phyp->target == target)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp->target = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh target->phy = NULL;
654ea33ca0109c50a5591204bec77a56aecdc522Srikanth Suravajhala if (phyp) {
654ea33ca0109c50a5591204bec77a56aecdc522Srikanth Suravajhala mutex_exit(&phyp->phy_lock);
654ea33ca0109c50a5591204bec77a56aecdc522Srikanth Suravajhala }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_destroy_target(target);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&target->statlock);
654ea33ca0109c50a5591204bec77a56aecdc522Srikanth Suravajhala if (phyp) {
654ea33ca0109c50a5591204bec77a56aecdc522Srikanth Suravajhala mutex_exit(&phyp->phy_lock);
654ea33ca0109c50a5591204bec77a56aecdc522Srikanth Suravajhala }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsa_start(struct scsi_address *ap, struct scsi_pkt *pkt)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_cmd_t *sp = PKT2CMD(pkt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = ADDR2PMC(ap);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *xp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh boolean_t blocked;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t hba_state;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: pkt %p sd %p cdb0=0x%02x dl=%lu", __func__, (void *)pkt,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)scsi_address_device(&pkt->pkt_address),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_cdbp[0] & 0xff, pkt->pkt_dma_len);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pkt->pkt_flags & FLAG_NOINTR) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG3, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: nointr pkt", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (TRAN_BADPKT);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sp->cmd_tag = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_state = pkt->pkt_statistics = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_reason = CMD_INCOMPLETE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh hba_state = pwp->state;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh blocked = pwp->blocked;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (hba_state != STATE_RUNNING) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: hba dead", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (TRAN_FATAL_ERROR);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp = pmcs_addr2xp(ap, NULL, sp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp == NULL) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: dropping due to null target", __func__);
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler goto dead_target;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&xp->statlock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler * First, check to see if the device is gone.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler if (xp->dev_gone) {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana xp->actv_pkts++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG3, NULL, xp,
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler "%s: dropping due to dead target 0x%p",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)xp);
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler goto dead_target;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we're blocked (quiesced) just return.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (blocked) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: hba blocked", __func__);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana xp->actv_pkts++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_TAIL(&xp->wq, sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (TRAN_ACCEPT);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we're draining or resetting, queue and return.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->draining || xp->resetting || xp->recover_wait) {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana xp->actv_pkts++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_TAIL(&xp->wq, sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->wqlock);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG1, NULL, xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: draining/resetting/recovering (cnt %u)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, xp->actv_cnt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * By the time we get here, draining or
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * resetting may have come and gone, not
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * yet noticing that we had put something
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * on the wait queue, so schedule a worker
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * to look at this later.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (TRAN_ACCEPT);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana xp->actv_pkts++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Queue this command to the tail of the wait queue.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This keeps us getting commands out of order.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_TAIL(&xp->wq, sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Now run the queue for this device.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_scsa_wq_run_one(pwp, xp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (TRAN_ACCEPT);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butlerdead_target:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_state = STATE_GOT_BUS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_reason = CMD_DEV_GONE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_TAIL(&pwp->cq, sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_CQ_RUN_LOCKED(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (TRAN_ACCEPT);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana/* Return code 1 = Success */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsa_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = ADDR2PMC(ap);
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana pmcs_cmd_t *sp = NULL;
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana pmcs_xscsi_t *xp = NULL;
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana pmcs_phy_t *pptr = NULL;
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana pmcs_lun_t *pmcs_lun = (pmcs_lun_t *)
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana scsi_device_hba_private_get(scsi_address_device(ap));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t tag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint64_t lun;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcwork_t *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->state != STATE_RUNNING) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: hba dead", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana if (pkt == NULL) {
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana if (pmcs_lun == NULL) {
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "%s: "
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana "No pmcs_lun_t struct to do ABORT_ALL", __func__);
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana return (0);
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana }
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana xp = pmcs_lun->target;
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana if (xp != NULL) {
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana pptr = xp->phy;
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana }
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana if (pptr == NULL) {
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, xp, "%s: pkt is "
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana "NULL. No tgt/phy to do ABORT_ALL", __func__);
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana return (0);
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana }
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana pmcs_lock_phy(pptr);
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana if (pmcs_abort(pwp, pptr, 0, 1, 0)) {
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana pptr->abort_pending = 1;
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana }
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana pmcs_unlock_phy(pptr);
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana return (1);
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana }
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana sp = PKT2CMD(pkt);
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana xp = sp->cmd_target;
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (sp->cmd_lun) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh lun = sp->cmd_lun->lun_num;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh lun = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * See if we have a real work structure associated with this cmd.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
978d7443a924cda8208d6a10e72be89383bc7becSrikanth Suravajhala pwrk = pmcs_tag2wp(pwp, sp->cmd_tag, B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk && pwrk->arg == sp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tag = pwrk->htag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pwrk->phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->timer = 0; /* we don't time this here */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pwrk->state == PMCS_WORK_STATE_ONCHIP);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr->dtype == SAS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_ssp_tmf(pwp, pptr, SAS_ABORT_TASK, tag, lun,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh NULL)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->abort_pending = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * XXX: Was the command that was active an
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * NCQ I/O command?
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->need_rl_ext = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_sata_abort_ncq(pwp, pptr)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->abort_pending = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->abort_pending = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Okay, those weren't the droids we were looking for.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * See if the command is on any of the wait queues.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sp = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_FOREACH(sp, &xp->wq, cmd_next) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (sp == PKT2CMD(pkt)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_REMOVE(&xp->wq, sp, pmcs_cmd, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (sp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_reason = CMD_ABORTED;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_statistics |= STAT_ABORTED;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_TAIL(&pwp->cq, sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_CQ_RUN_LOCKED(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * SCSA reset functions
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsa_reset(struct scsi_address *ap, int level)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = ADDR2PMC(ap);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *xp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint64_t lun = (uint64_t)-1, *lp = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int rval;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->state != STATE_RUNNING) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: hba dead", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (level) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case RESET_ALL:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case RESET_LUN:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Point lp at lun so that pmcs_addr2xp
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * will fill out the 64 bit lun number.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh lp = &lun;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* FALLTHROUGH */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case RESET_TARGET:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp = pmcs_addr2xp(ap, lp, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp == NULL) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: no xp found for this scsi address", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler if (xp->dev_gone) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Target 0x%p has gone away", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)xp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we're already performing this action, or if device
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * state recovery is already running, just return failure.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->resetting || xp->recover_wait) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->reset_wait = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->reset_success = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->resetting = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = xp->phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_reset_dev(pwp, pptr, lun)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rval == 1) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->reset_success = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->reset_wait) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->reset_wait = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_signal(&xp->reset_cv);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->resetting = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (rval);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsi_reset_notify(struct scsi_address *ap, int flag,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh void (*callback)(caddr_t), caddr_t arg)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = ADDR2PMC(ap);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &pwp->lock, &pwp->reset_notify_listf));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_cap(struct scsi_address *ap, char *cap, int val, int tonly, int set)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh _NOTE(ARGUNUSED(val, tonly));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int cidx, rval = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *xp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cidx = scsi_hba_lookup_capstr(cap);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (cidx == -1) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp = pmcs_addr2xp(ap, NULL, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (cidx) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCSI_CAP_DMA_MAX:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCSI_CAP_INITIATOR_ID:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (set == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = INT_MAX; /* argh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCSI_CAP_DISCONNECT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCSI_CAP_SYNCHRONOUS:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCSI_CAP_WIDE_XFER:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCSI_CAP_PARITY:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCSI_CAP_ARQ:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCSI_CAP_UNTAGGED_QING:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (set == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCSI_CAP_TAGGED_QING:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCSI_CAP_MSG_OUT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCSI_CAP_RESET_NOTIFICATION:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCSI_CAP_QFULL_RETRIES:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCSI_CAP_QFULL_RETRY_INTERVAL:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCSI_CAP_SCSI_VERSION:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (set == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = SCSI_VERSION_3;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCSI_CAP_INTERCONNECT_TYPE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (set) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->phy_addressable) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = INTERCONNECT_SATA;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = INTERCONNECT_SAS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCSI_CAP_CDB_LEN:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (set == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = 16;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCSI_CAP_LUN_RESET:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (set) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->dtype == SATA) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = -1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(ADDR2PMC(ap), PMCS_PRT_DEBUG3, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: cap %s val %d set %d rval %d",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, cap, val, set, rval);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (rval);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Returns with statlock held if the xp is found.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Fills in pmcs_cmd_t with values if pmcs_cmd_t pointer non-NULL.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic pmcs_xscsi_t *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_addr2xp(struct scsi_address *ap, uint64_t *lp, pmcs_cmd_t *sp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *xp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lun_t *lun = (pmcs_lun_t *)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_device_hba_private_get(scsi_address_device(ap));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((lun == NULL) || (lun->target == NULL)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp = lun->target;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler if (xp->dev_gone || (xp->phy == NULL)) {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana /*
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana * This may be a retried packet, so it's possible cmd_target
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana * and cmd_lun may still be populated. Clear them.
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana */
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana if (sp != NULL) {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana sp->cmd_target = NULL;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana sp->cmd_lun = NULL;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (sp != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sp->cmd_target = xp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sp->cmd_lun = lun;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (lp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *lp = lun->lun_num;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (xp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsa_getcap(struct scsi_address *ap, char *cap, int whom)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int r;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (cap == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh r = pmcs_cap(ap, cap, 0, whom, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (r);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsa_setcap(struct scsi_address *ap, char *cap, int value, int whom)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int r;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (cap == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh r = pmcs_cap(ap, cap, value, whom, 1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (r);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsa_setup_pkt(struct scsi_pkt *pkt, int (*callback)(caddr_t),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh caddr_t cbarg)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh _NOTE(ARGUNUSED(callback, cbarg));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_cmd_t *sp = pkt->pkt_ha_private;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(sp, sizeof (pmcs_cmd_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sp->cmd_pkt = pkt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsa_teardown_pkt(struct scsi_pkt *pkt)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_cmd_t *sp = pkt->pkt_ha_private;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sp->cmd_target = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sp->cmd_lun = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Hornepmcs_smp_start(struct smp_pkt *smp_pkt)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct pmcwork *pwrk;
3be32c0f0acac4f6258b029f1a27a16a7ec65bb0Jesse Butler pmcs_iport_t *iport;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh const uint_t rdoff = SAS_SMP_MAX_PAYLOAD;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t msg[PMCS_MSG_SIZE], *ptr, htag, status;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint64_t wwn;
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne pmcs_hw_t *pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *xp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint_t reqsz, rspsz, will_retry;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int result;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne pwp = smp_pkt->smp_pkt_address->smp_a_hba_tran->smp_tran_hba_private;
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne bcopy(smp_pkt->smp_pkt_address->smp_a_wwn, &wwn, SAS_WWN_BYTE_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG1, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: starting for wwn 0x%" PRIx64, __func__, wwn);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne will_retry = smp_pkt->smp_pkt_will_retry;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_acquire_scratch(pwp, B_TRUE);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne reqsz = smp_pkt->smp_pkt_reqsize;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (reqsz > SAS_SMP_MAX_PAYLOAD) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh reqsz = SAS_SMP_MAX_PAYLOAD;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne (void) memcpy(pwp->scratch, smp_pkt->smp_pkt_req, reqsz);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne rspsz = smp_pkt->smp_pkt_rspsize;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rspsz > SAS_SMP_MAX_PAYLOAD) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rspsz = SAS_SMP_MAX_PAYLOAD;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The request size from the SMP driver always includes 4 bytes
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * for the CRC. The PMCS chip, however, doesn't want to see those
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * counts as part of the transfer size.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh reqsz -= 4;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr = pmcs_find_phy_by_wwn(pwp, wwn);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* PHY is now locked */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr == NULL || pptr->dtype != EXPANDER) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pptr) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_release_scratch(pwp);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: could not find phy", __func__);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_reason = ENXIO;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister if ((pptr->iport == NULL) || !pptr->valid_device_id) {
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_unlock_phy(pptr);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_release_scratch(pwp);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, pptr->target,
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister "%s: Can't reach PHY %s", __func__, pptr->path);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister smp_pkt->smp_pkt_reason = ENXIO;
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister return (DDI_FAILURE);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister }
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_release_scratch(pwp);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: could not get work structure", __func__);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_reason = will_retry ? EAGAIN : EBUSY;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->arg = msg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->dtype = EXPANDER;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ptr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_release_scratch(pwp);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: could not get IQ entry", __func__);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_reason = will_retry ? EAGAIN :EBUSY;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
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(SMP_INDIRECT_RESPONSE | SMP_INDIRECT_REQUEST);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[8] = LE_32(DWORD0(pwp->scratch_dma));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[9] = LE_32(DWORD1(pwp->scratch_dma));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[10] = LE_32(reqsz);
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(rspsz);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[15] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh COPY_MESSAGE(ptr, msg, PMCS_MSG_SIZE);
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler
3be32c0f0acac4f6258b029f1a27a16a7ec65bb0Jesse Butler pmcs_hold_iport(pptr->iport);
3be32c0f0acac4f6258b029f1a27a16a7ec65bb0Jesse Butler iport = pptr->iport;
3be32c0f0acac4f6258b029f1a27a16a7ec65bb0Jesse Butler pmcs_smp_acquire(iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh htag = pwrk->htag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne WAIT_FOR(pwrk, smp_pkt->smp_pkt_timeout * 1000, result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
827ab345d60a068feceedd00074fed206c7f154cJesse Butler pmcs_smp_release(iport);
827ab345d60a068feceedd00074fed206c7f154cJesse Butler pmcs_rele_iport(iport);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (result) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_timed_out(pwp, htag, __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_abort(pwp, pptr, htag, 0, 0)) {
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, pptr->target,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Unable to issue SMP ABORT for htag 0x%08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, pptr->target,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Issuing SMP ABORT for htag 0x%08x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_release_scratch(pwp);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_reason = ETIMEDOUT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh status = LE_32(msg[2]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (status == PMCOUT_STATUS_OVERFLOW) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh status = PMCOUT_STATUS_OK;
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_reason = EOVERFLOW;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (status != PMCOUT_STATUS_OK) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh const char *emsg = pmcs_status_str(status);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (emsg == NULL) {
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, pptr->target,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "SMP operation failed (0x%x)", status);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, pptr->target,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "SMP operation failed (%s)", emsg);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((status == PMCOUT_STATUS_ERROR_HW_TIMEOUT) ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (status == PMCOUT_STATUS_IO_XFER_OPEN_RETRY_TIMEOUT)) {
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_reason =
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne will_retry ? EAGAIN : ETIMEDOUT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = DDI_FAILURE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (status ==
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCOUT_STATUS_OPEN_CNX_ERROR_IT_NEXUS_LOSS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp = pptr->target;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp == NULL) {
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_reason = EIO;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = DDI_FAILURE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->dev_state !=
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_DEVICE_STATE_NON_OPERATIONAL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->dev_state =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_DEVICE_STATE_NON_OPERATIONAL;
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, xp->phy,
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister xp, "%s: Got _IT_NEXUS_LOSS SMP status. "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Tgt(0x%p) dev_state set to "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "_NON_OPERATIONAL", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)xp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* ABORT any pending commands related to this device */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_abort(pwp, pptr, pptr->device_id, 1, 1) != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->abort_pending = 1;
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_reason = EIO;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = DDI_FAILURE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_reason = will_retry ? EAGAIN : EIO;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = DDI_FAILURE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne (void) memcpy(smp_pkt->smp_pkt_rsp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh &((uint8_t *)pwp->scratch)[rdoff], rspsz);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne if (smp_pkt->smp_pkt_reason == EOVERFLOW) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = DDI_FAILURE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh result = DDI_SUCCESS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhout:
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG1, pptr, pptr->target,
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister "%s: done for wwn 0x%" PRIx64, __func__, wwn);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_release_scratch(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (result);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_smp_init(dev_info_t *self, dev_info_t *child,
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_hba_tran_t *tran, smp_device_t *smp_sd)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne _NOTE(ARGUNUSED(tran, smp_sd));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_iport_t *iport;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *tgt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *phy, *pphy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint64_t wwn;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char *addr, *tgt_port;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int ua_form = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport = ddi_get_soft_state(pmcs_iport_softstate,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_get_instance(self));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (iport == NULL)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp = iport->pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp == NULL)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Get "target-port" prop from devinfo node */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCSI_ADDR_PROP_TARGET_PORT, &tgt_port) != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "%s: Failed to "
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "lookup prop ("SCSI_ADDR_PROP_TARGET_PORT")", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Dont fail _smp_init() because we couldnt get/set a prop */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Validate that this tran_tgt_init is for an active iport.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (iport->ua_state == UA_INACTIVE) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: Init on inactive iport for '%s'", __func__, tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_prop_free(tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Retrieve softstate using unit-address */
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler tgt = pmcs_get_target(iport, tgt_port, B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt == NULL) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: tgt softstate not found", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_prop_free(tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, tgt, "%s: %s (%s)",
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister __func__, ddi_get_name(child), tgt_port);
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister mutex_enter(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phy = tgt->phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(mutex_owned(&phy->phy_lock));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (IS_ROOT_PHY(phy)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Expander attached to HBA - don't ref_count it */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh wwn = pwp->sas_wwns[0];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_inc_phy_ref_count(phy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Parent (in topology) is also an expander
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Now that we've increased the ref count on phy, it's OK
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * to drop the lock so we can acquire the parent's lock.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pphy = phy->parent;
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pphy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh wwn = pmcs_barray2wwn(pphy->sas_address);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pphy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(phy);
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister mutex_enter(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If this is the 1st smp_init, add this to our list.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt->target_num == PMCS_INVALID_TARGET_NUM) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int target;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (target = 0; target < pwp->max_dev; target++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->targets[target] != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->targets[target] = tgt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->target_num = (uint16_t)target;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->assigned = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->dev_state = PMCS_DEVICE_STATE_OPERATIONAL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (target == pwp->max_dev) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Target list full.");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto smp_init_fail;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!pmcs_assign_device(pwp, tgt)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->targets[tgt->target_num] = NULL;
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, tgt,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: pmcs_assign_device failed for target 0x%p",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto smp_init_fail;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
499cfd156ad653fc27397c5f021047c091dd12c5David Hollister /*
499cfd156ad653fc27397c5f021047c091dd12c5David Hollister * Update the attached port and target port pm properties
499cfd156ad653fc27397c5f021047c091dd12c5David Hollister */
499cfd156ad653fc27397c5f021047c091dd12c5David Hollister tgt->smpd = smp_sd;
499cfd156ad653fc27397c5f021047c091dd12c5David Hollister
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->ref_count++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->dtype = phy->dtype;
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister mutex_exit(&tgt->statlock);
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister pmcs_update_phy_pm_props(phy, 0, 0, B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh addr = scsi_wwn_to_wwnstr(wwn, ua_form, NULL);
499cfd156ad653fc27397c5f021047c091dd12c5David Hollister if (smp_device_prop_update_string(smp_sd, SCSI_ADDR_PROP_ATTACHED_PORT,
499cfd156ad653fc27397c5f021047c091dd12c5David Hollister addr) != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "%s: Failed to set "
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "prop ("SCSI_ADDR_PROP_ATTACHED_PORT")", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) scsi_free_wwnstr(addr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_prop_free(tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhsmp_init_fail:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->phy = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->target_num = PMCS_INVALID_TARGET_NUM;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phy->target = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!IS_ROOT_PHY(phy)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dec_phy_ref_count(phy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_bystr_free(iport->tgt_sstate, tgt->unit_address);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_prop_free(tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (DDI_FAILURE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_smp_free(dev_info_t *self, dev_info_t *child,
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_hba_tran_t *tran, smp_device_t *smp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh _NOTE(ARGUNUSED(tran, smp));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_iport_t *iport;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *tgt;
ee13933a0bbf5c72c183bd6af13573d82b78856aSrikanth Suravajhala pmcs_phy_t *phyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char *tgt_port;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh iport = ddi_get_soft_state(pmcs_iport_softstate,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_get_instance(self));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(iport);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (iport == NULL)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp = iport->pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp == NULL)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Get "target-port" prop from devinfo node */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_prop_lookup_string(DDI_DEV_T_ANY, child,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_PROP_DONTPASS | DDI_PROP_NOTPROM,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCSI_ADDR_PROP_TARGET_PORT, &tgt_port) != DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "%s: Failed to "
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "lookup prop ("SCSI_ADDR_PROP_TARGET_PORT")", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Retrieve softstate using unit-address */
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt = ddi_soft_state_bystr_get(iport->tgt_sstate, tgt_port);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, tgt, "%s: %s (%s)", __func__,
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister ddi_get_name(child), tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_prop_free(tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt == NULL) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: tgt softstate not found", __func__);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
ee13933a0bbf5c72c183bd6af13573d82b78856aSrikanth Suravajhala phyp = tgt->phy;
ee13933a0bbf5c72c183bd6af13573d82b78856aSrikanth Suravajhala if (phyp) {
ee13933a0bbf5c72c183bd6af13573d82b78856aSrikanth Suravajhala mutex_enter(&phyp->phy_lock);
ee13933a0bbf5c72c183bd6af13573d82b78856aSrikanth Suravajhala if (!IS_ROOT_PHY(phyp)) {
ee13933a0bbf5c72c183bd6af13573d82b78856aSrikanth Suravajhala pmcs_dec_phy_ref_count(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
ee13933a0bbf5c72c183bd6af13573d82b78856aSrikanth Suravajhala mutex_enter(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (--tgt->ref_count == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Remove this target from our list. The softstate
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * will remain, and the device will remain registered
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * with the hardware unless/until we're told that the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * device physically went away.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, tgt,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Removing target 0x%p (vtgt %d) from target list",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)tgt, tgt->target_num);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->targets[tgt->target_num] = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->target_num = PMCS_INVALID_TARGET_NUM;
6c87a171a391b9e1c12d8fb7f74466f7e6e637afJesse Butler /* If the PHY has a pointer to this target, clear it */
6c87a171a391b9e1c12d8fb7f74466f7e6e637afJesse Butler if (phyp && (phyp->target == tgt)) {
ee13933a0bbf5c72c183bd6af13573d82b78856aSrikanth Suravajhala phyp->target = NULL;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler }
ee13933a0bbf5c72c183bd6af13573d82b78856aSrikanth Suravajhala tgt->phy = NULL;
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_destroy_target(tgt);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister } else {
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
ee13933a0bbf5c72c183bd6af13573d82b78856aSrikanth Suravajhala if (phyp) {
ee13933a0bbf5c72c183bd6af13573d82b78856aSrikanth Suravajhala mutex_exit(&phyp->phy_lock);
ee13933a0bbf5c72c183bd6af13573d82b78856aSrikanth Suravajhala }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsi_quiesce(dev_info_t *dip)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int totactive = -1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *xp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint16_t target;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_get_soft_state(pmcs_iport_softstate, ddi_get_instance(dip)))
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0); /* iport */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp = ddi_get_soft_state(pmcs_softc_state, ddi_get_instance(dip));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->state != STATE_RUNNING) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "%s called", __func__);
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pwp->quiesced = pwp->blocked = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (totactive) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh totactive = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (target = 0; target < pwp->max_dev; target++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp = pwp->targets[target];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->actv_cnt) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh totactive += xp->actv_cnt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->draining = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (totactive) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_wait(&pwp->drain_cv, &pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The pwp->blocked may have been reset. e.g a SCSI bus reset
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->blocked = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (target = 0; target < pwp->max_dev; target++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp = pwp->targets[target];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->draining = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (totactive == 0) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, xp,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s drain complete", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsi_unquiesce(dev_info_t *dip)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_get_soft_state(pmcs_iport_softstate, ddi_get_instance(dip)))
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0); /* iport */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp = ddi_get_soft_state(pmcs_softc_state, ddi_get_instance(dip));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwp->state != STATE_RUNNING) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "%s called", __func__);
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pwp->blocked = pwp->quiesced = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Run all pending commands.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_scsa_wq_run(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Complete all completed commands.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This also unlocks us.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_CQ_RUN(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Start commands for a particular device
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the actual start of a command fails, return B_FALSE. Any other result
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * is a B_TRUE return.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhboolean_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsa_wq_run_one(pmcs_hw_t *pwp, pmcs_xscsi_t *xp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_cmd_t *sp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *phyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcwork_t *pwrk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh boolean_t run_one, blocked;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int rval;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * First, check to see if we're blocked or resource limited
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh blocked = pwp->blocked;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If resource_limited is set, we're resource constrained and
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * we will run only one work request for this target.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh run_one = pwp->resource_limited;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (blocked) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Queues will get restarted when we get unblocked */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Might as well verify the queue is not empty before moving on
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (STAILQ_EMPTY(&xp->wq)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we're draining or resetting, just reschedule work queue and bail.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->draining || xp->resetting || xp->special_running ||
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->special_needed) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler * Next, check to see if the target is gone.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler if (xp->dev_gone) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, xp,
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler "%s: Flushing wait queue for dead tgt 0x%p", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)xp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_flush_target_queues(pwp, xp, PMCS_TGT_WAIT_QUEUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Increment the PHY's ref_count now so we know it won't go away
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * after we drop the target lock. Drop it before returning. If the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * PHY dies, the commands we attempt to send will fail, but at least
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * we know we have a real PHY pointer.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = xp->phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_inc_phy_ref_count(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while ((sp = STAILQ_FIRST(&xp->wq)) != NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_CBACK, phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk == NULL) {
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister mutex_exit(&xp->wqlock);
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister mutex_enter(&pwp->lock);
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister if (pwp->resource_limited == 0) {
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister "%s: out of work structures", __func__);
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister }
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister pwp->resource_limited = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES);
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister mutex_exit(&pwp->lock);
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_REMOVE_HEAD(&xp->wq, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->xp = xp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->arg = sp;
b53bcbf6c7a28e7236bed3897a3b88444e9e9f7dSrikanth Suravajhala pwrk->timer = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sp->cmd_tag = pwrk->htag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->dtype = xp->dtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->dtype == SAS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->ptr = (void *) pmcs_SAS_done;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((rval = pmcs_SAS_run(sp, pwrk)) != 0) {
5a7797ce9bcfe70ce0ab366abc3051dce3cede6fJesse Butler if (rval != PMCS_WQ_RUN_FAIL_RES_CMP) {
5a7797ce9bcfe70ce0ab366abc3051dce3cede6fJesse Butler sp->cmd_tag = NULL;
5a7797ce9bcfe70ce0ab366abc3051dce3cede6fJesse Butler }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dec_phy_ref_count(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rval == PMCS_WQ_RUN_FAIL_RES) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(xp->dtype == SATA);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->ptr = (void *) pmcs_SATA_done;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((rval = pmcs_SATA_run(sp, pwrk)) != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sp->cmd_tag = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dec_phy_ref_count(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rval == PMCS_WQ_RUN_FAIL_RES) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (run_one) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto wq_out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhwq_out:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dec_phy_ref_count(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Start commands for all devices.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsa_wq_run(pmcs_hw_t *pwp)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *xp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint16_t target_start, target;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh boolean_t rval = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh target_start = pwp->last_wq_dev;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh target = target_start;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh do {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp = pwp->targets[target];
429adc13c4b769a844f808af172a087750ae2e90Srikanth, Ramana if ((xp == NULL) || (STAILQ_EMPTY(&xp->wq))) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (++target == pwp->max_dev) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh target = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh continue;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = pmcs_scsa_wq_run_one(pwp, xp);
429adc13c4b769a844f808af172a087750ae2e90Srikanth, Ramana mutex_enter(&pwp->lock);
429adc13c4b769a844f808af172a087750ae2e90Srikanth, Ramana
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rval == B_FALSE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
429adc13c4b769a844f808af172a087750ae2e90Srikanth, Ramana
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (++target == pwp->max_dev) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh target = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } while (target != target_start);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rval) {
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister /*
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister * If we were resource limited, but apparently are not now,
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister * reschedule the work queues anyway.
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister */
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister if (pwp->resource_limited) {
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES);
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->resource_limited = 0; /* Not resource-constrained */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister /*
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister * Give everybody a chance, and reschedule to run the queues
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister * again as long as we're limited.
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister */
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister pwp->resource_limited = 1;
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->last_wq_dev = target;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Pull the completion queue, drop the lock and complete all elements.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsa_cq_run(void *arg)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_cq_thr_info_t *cqti = (pmcs_cq_thr_info_t *)arg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = cqti->cq_pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_cmd_t *sp, *nxt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct scsi_pkt *pkt;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pmcs_xscsi_t *tgt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_iocomp_cb_t *ioccb, *ioccb_next;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_cb_t callback;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DTRACE_PROBE1(pmcs__scsa__cq__run__start, pmcs_cq_thr_info_t *, cqti);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (!pwp->cq_info.cq_stop) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * First, check the I/O completion callback queue.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ioccb = pwp->iocomp_cb_head;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->iocomp_cb_head = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->iocomp_cb_tail = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (ioccb) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Grab the lock on the work structure. The callback
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * routine is responsible for clearing it.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&ioccb->pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ioccb_next = ioccb->next;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh callback = (pmcs_cb_t)ioccb->pwrk->ptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (*callback)(pwp, ioccb->pwrk,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (uint32_t *)((void *)ioccb->iomb));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh kmem_cache_free(pwp->iocomp_cb_cache, ioccb);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ioccb = ioccb_next;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Next, run the completion queue
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sp = STAILQ_FIRST(&pwp->cq);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INIT(&pwp->cq);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DTRACE_PROBE1(pmcs__scsa__cq__run__start__loop,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_cq_thr_info_t *, cqti);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (sp && pmcs_check_acc_dma_handle(pwp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_fm_service_impact(pwp->dip, DDI_SERVICE_UNAFFECTED);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (sp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh nxt = STAILQ_NEXT(sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt = CMD2PKT(sp);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana tgt = sp->cmd_target;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pmcs_prt(pwp, PMCS_PRT_DEBUG3, NULL, tgt,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: calling completion on %p for tgt %p", __func__,
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana (void *)sp, (void *)tgt);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana if (tgt) {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana mutex_enter(&tgt->statlock);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana ASSERT(tgt->actv_pkts != 0);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana tgt->actv_pkts--;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana mutex_exit(&tgt->statlock);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_hba_pkt_comp(pkt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sp = nxt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DTRACE_PROBE1(pmcs__scsa__cq__run__end__loop,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_cq_thr_info_t *, cqti);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
8f514e743bde41fe7e0ca48510a6d4c40ca51c23David Hollister /*
8f514e743bde41fe7e0ca48510a6d4c40ca51c23David Hollister * Check if there are more completions to do. If so, and we've
8f514e743bde41fe7e0ca48510a6d4c40ca51c23David Hollister * not been told to stop, skip the wait and cycle through again.
8f514e743bde41fe7e0ca48510a6d4c40ca51c23David Hollister */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->cq_lock);
8f514e743bde41fe7e0ca48510a6d4c40ca51c23David Hollister if ((pwp->iocomp_cb_head == NULL) && STAILQ_EMPTY(&pwp->cq) &&
8f514e743bde41fe7e0ca48510a6d4c40ca51c23David Hollister !pwp->cq_info.cq_stop) {
8f514e743bde41fe7e0ca48510a6d4c40ca51c23David Hollister mutex_exit(&pwp->cq_lock);
8f514e743bde41fe7e0ca48510a6d4c40ca51c23David Hollister mutex_enter(&cqti->cq_thr_lock);
8f514e743bde41fe7e0ca48510a6d4c40ca51c23David Hollister cv_wait(&cqti->cq_cv, &cqti->cq_thr_lock);
8f514e743bde41fe7e0ca48510a6d4c40ca51c23David Hollister mutex_exit(&cqti->cq_thr_lock);
8f514e743bde41fe7e0ca48510a6d4c40ca51c23David Hollister mutex_enter(&pwp->cq_lock);
8f514e743bde41fe7e0ca48510a6d4c40ca51c23David Hollister }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DTRACE_PROBE1(pmcs__scsa__cq__run__stop, pmcs_cq_thr_info_t *, cqti);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh thread_exit();
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Run a SAS command. Called with pwrk->lock held, returns unlocked.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_SAS_run(pmcs_cmd_t *sp, pmcwork_t *pwrk)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = CMD2PMC(sp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct scsi_pkt *pkt = CMD2PKT(sp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *xp = pwrk->xp;
69b2e2313400e7ae0a61f2d7cb0a04ff176dfff6Srikanth Suravajhala uint32_t iq, lhtag, *ptr;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sas_ssp_cmd_iu_t sc;
69b2e2313400e7ae0a61f2d7cb0a04ff176dfff6Srikanth Suravajhala int sp_pkt_time = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
3be32c0f0acac4f6258b029f1a27a16a7ec65bb0Jesse Butler ASSERT(xp != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler if (!xp->assigned) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (PMCS_WQ_RUN_FAIL_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((xp->actv_cnt >= xp->qdepth) || xp->recover_wait) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_HEAD(&xp->wq, sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (PMCS_WQ_RUN_FAIL_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh GET_IO_IQ_ENTRY(pwp, ptr, pwrk->phy->device_id, iq);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ptr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This is a temporary failure not likely to unblocked by
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * commands completing as the test for scheduling the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * restart of work is a per-device test.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_HEAD(&xp->wq, sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->wqlock);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Failed to get IO IQ entry for tgt %d",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, xp->target_num);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (PMCS_WQ_RUN_FAIL_RES);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr[0] =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh LE_32(PMCS_IOMB_IN_SAS(PMCS_OQ_IODONE, PMCIN_SSP_INI_IO_START));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr[2] = LE_32(pwrk->phy->device_id);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr[3] = LE_32(pkt->pkt_dma_len);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ptr[3]) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pkt->pkt_numcookies);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pkt->pkt_dma_flags & DDI_DMA_READ) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr[4] = LE_32(PMCIN_DATADIR_2_INI);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr[4] = LE_32(PMCIN_DATADIR_2_DEV);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_dma_load(pwp, sp, ptr)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[iq]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (STAILQ_EMPTY(&xp->wq)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_HEAD(&xp->wq, sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->wqlock);
5a7797ce9bcfe70ce0ab366abc3051dce3cede6fJesse Butler return (PMCS_WQ_RUN_FAIL_RES);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CMD2PKT(sp)->pkt_scbp[0] = STATUS_QFULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CMD2PKT(sp)->pkt_reason = CMD_CMPLT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CMD2PKT(sp)->pkt_state |= STATE_GOT_BUS |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STATE_GOT_TARGET | STATE_SENT_CMD |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STATE_GOT_STATUS;
5a7797ce9bcfe70ce0ab366abc3051dce3cede6fJesse Butler sp->cmd_tag = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_TAIL(&pwp->cq, sp, cmd_next);
8f514e743bde41fe7e0ca48510a6d4c40ca51c23David Hollister PMCS_CQ_RUN_LOCKED(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->cq_lock);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Failed to dma_load for tgt %d (QF)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, xp->target_num);
5a7797ce9bcfe70ce0ab366abc3051dce3cede6fJesse Butler return (PMCS_WQ_RUN_FAIL_RES_CMP);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr[4] = LE_32(PMCIN_DATADIR_NONE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CLEAN_MESSAGE(ptr, 12);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->actv_cnt++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->actv_cnt > xp->maxdepth) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->maxdepth = xp->actv_cnt;
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG2, pwrk->phy, xp, "%s: max depth "
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "now %u", pwrk->phy->path, xp->maxdepth);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#ifdef DEBUG
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Generate a PMCOUT_STATUS_XFER_CMD_FRAME_ISSUED
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * event when this goes out on the wire.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr[4] |= PMCIN_MESSAGE_REPORT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#endif
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Fill in the SSP IU
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(&sc, sizeof (sas_ssp_cmd_iu_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bcopy((uint8_t *)&sp->cmd_lun->scsi_lun, sc.lun, sizeof (scsi_lun_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (pkt->pkt_flags & FLAG_TAGMASK) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case FLAG_HTAG:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sc.task_attribute = SAS_CMD_TASK_ATTR_HEAD;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case FLAG_OTAG:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sc.task_attribute = SAS_CMD_TASK_ATTR_ORDERED;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case FLAG_STAG:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sc.task_attribute = SAS_CMD_TASK_ATTR_SIMPLE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(sc.cdb, pkt->pkt_cdbp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh min(SCSA_CDBLEN(sp), sizeof (sc.cdb)));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(&ptr[5], &sc, sizeof (sas_ssp_cmd_iu_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
69b2e2313400e7ae0a61f2d7cb0a04ff176dfff6Srikanth Suravajhala lhtag = pwrk->htag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: giving pkt %p (tag %x) to the hardware", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)pkt, pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#ifdef DEBUG
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_print_entry(pwp, PMCS_PRT_DEBUG3, "SAS INI Message", ptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#endif
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->aqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_TAIL(&xp->aq, sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->aqlock);
69b2e2313400e7ae0a61f2d7cb0a04ff176dfff6Srikanth Suravajhala sp_pkt_time = CMD2PKT(sp)->pkt_time;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, iq);
b53bcbf6c7a28e7236bed3897a3b88444e9e9f7dSrikanth Suravajhala mutex_enter(&pwrk->lock);
69b2e2313400e7ae0a61f2d7cb0a04ff176dfff6Srikanth Suravajhala if (lhtag == pwrk->htag) {
69b2e2313400e7ae0a61f2d7cb0a04ff176dfff6Srikanth Suravajhala pwrk->timer = US2WT(sp_pkt_time * 1000000);
69b2e2313400e7ae0a61f2d7cb0a04ff176dfff6Srikanth Suravajhala if (pwrk->timer == 0) {
69b2e2313400e7ae0a61f2d7cb0a04ff176dfff6Srikanth Suravajhala pwrk->timer = US2WT(1000000);
69b2e2313400e7ae0a61f2d7cb0a04ff176dfff6Srikanth Suravajhala }
b53bcbf6c7a28e7236bed3897a3b88444e9e9f7dSrikanth Suravajhala }
b53bcbf6c7a28e7236bed3897a3b88444e9e9f7dSrikanth Suravajhala mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we just submitted the last command queued from device state
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * recovery, clear the wq_recovery_tail pointer.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->wq_recovery_tail == sp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->wq_recovery_tail = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (PMCS_WQ_RUN_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Complete a SAS command
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with pwrk lock held.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The free of pwrk releases the lock.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_SAS_done(pmcs_hw_t *pwp, pmcwork_t *pwrk, uint32_t *msg)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_cmd_t *sp = pwrk->arg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr = pwrk->phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *xp = pwrk->xp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct scsi_pkt *pkt = CMD2PKT(sp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int dead;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t sts;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh boolean_t aborted = B_FALSE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh boolean_t do_ds_recovery = B_FALSE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(xp != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(sp != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(pptr != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DTRACE_PROBE4(pmcs__io__done, uint64_t, pkt->pkt_dma_len, int,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pkt->pkt_dma_flags & DDI_DMA_READ) != 0, hrtime_t, pwrk->start,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh hrtime_t, gethrtime());
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh dead = pwrk->dead;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (msg) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sts = LE_32(msg[2]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sts = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (dead != 0) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp, "%s: dead cmd tag "
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "0x%x for %s", __func__, pwrk->htag, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (sts == PMCOUT_STATUS_ABORTED) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh aborted = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk->state == PMCS_WORK_STATE_TIMED_OUT) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: cmd 0x%p (tag 0x%x) timed out for %s",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)sp, pwrk->htag, pptr->path);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana CMD2PKT(sp)->pkt_scbp[0] = STATUS_GOOD;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana CMD2PKT(sp)->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET |
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana STATE_SENT_CMD;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana CMD2PKT(sp)->pkt_statistics |= STAT_TIMEOUT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the status isn't okay but not underflow,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * step to the side and parse the (possible) error.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#ifdef DEBUG
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (msg) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_print_entry(pwp, PMCS_PRT_DEBUG3, "Outbound Message", msg);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#endif
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!msg) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (sts) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_IO_DS_NON_OPERATIONAL:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_IO_DS_IN_RECOVERY:
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana "%s: PHY %s requires DS recovery (status=%d)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, pptr->path, sts);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh do_ds_recovery = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_UNDERFLOW:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_set_resid(pkt, pkt->pkt_dma_len, LE_32(msg[3]));
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_UNDERFLOW, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: underflow %u for cdb 0x%x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, LE_32(msg[3]), pkt->pkt_cdbp[0] & 0xff);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sts = PMCOUT_STATUS_OK;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[3] = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OK:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_resid = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (sts != PMCOUT_STATUS_OK) {
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister pmcs_ioerror(pwp, SAS, pwrk, msg, sts);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (msg[3]) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t local[PMCS_QENTRY_SIZE << 1], *xd;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sas_ssp_rsp_iu_t *rptr = (void *)local;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh const int lim =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (PMCS_QENTRY_SIZE << 1) - SAS_RSP_HDR_SIZE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh static const uint8_t ssp_rsp_evec[] = {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 0x58, 0x61, 0x56, 0x72, 0x00
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh };
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Transform the the first part of the response
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * to host canonical form. This gives us enough
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * information to figure out what to do with the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * rest (which remains unchanged in the incoming
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * message which can be up to two queue entries
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * in length).
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_endian_transform(pwp, local, &msg[5],
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ssp_rsp_evec);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xd = (uint8_t *)(&msg[5]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xd += SAS_RSP_HDR_SIZE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rptr->datapres == SAS_RSP_DATAPRES_RESPONSE_DATA) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rptr->response_data_length != 4) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_print_entry(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Bad SAS RESPONSE DATA LENGTH",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_reason = CMD_TRAN_ERR;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(&sts, xd, sizeof (uint32_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sts = BE_32(sts);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The only response code we should legally get
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * here is an INVALID FRAME response code.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (sts == SAS_RSP_INVALID_FRAME) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: pkt %p tgt %u path %s "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "completed: INVALID FRAME response",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)pkt,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->target_num, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: pkt %p tgt %u path %s "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "completed: illegal response 0x%x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)pkt,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->target_num, pptr->path, sts);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_reason = CMD_TRAN_ERR;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (rptr->datapres == SAS_RSP_DATAPRES_SENSE_DATA) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t slen;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh slen = rptr->sense_data_length;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (slen > lim) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh slen = lim;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_latch_status(pwp, sp, rptr->status, xd,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh slen, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (rptr->datapres == SAS_RSP_DATAPRES_NO_DATA) {
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister pmcout_ssp_comp_t *sspcp;
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister sspcp = (pmcout_ssp_comp_t *)msg;
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister uint32_t *residp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This is the case for a plain SCSI status.
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister * Note: If RESC_V is set and we're here, there
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister * is a residual. We need to find it and update
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister * the packet accordingly.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_latch_status(pwp, sp, rptr->status, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 0, pptr->path);
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister if (sspcp->resc_v) {
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister /*
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister * Point residual to the SSP_RESP_IU
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister */
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister residp = (uint32_t *)(sspcp + 1);
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister /*
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister * param contains the number of bytes
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister * between where the SSP_RESP_IU may
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister * or may not be and the residual.
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister * Increment residp by the appropriate
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister * number of words: (param+resc_pad)/4).
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister */
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister residp += (LE_32(sspcp->param) +
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister sspcp->resc_pad) /
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister sizeof (uint32_t);
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG_UNDERFLOW,
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister pptr, xp, "%s: tgt 0x%p "
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister "residual %d for pkt 0x%p",
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister __func__, (void *) xp, *residp,
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister (void *) pkt);
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister ASSERT(LE_32(*residp) <=
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister pkt->pkt_dma_len);
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister (void) pmcs_set_resid(pkt,
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister pkt->pkt_dma_len, LE_32(*residp));
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_print_entry(pwp, PMCS_PRT_DEBUG,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "illegal SAS response", msg);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_reason = CMD_TRAN_ERR;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_latch_status(pwp, sp, STATUS_GOOD, NULL, 0,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pkt->pkt_dma_len) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_state |= STATE_XFERRED_DATA;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG2, pptr, xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: pkt %p tgt %u done reason=%x state=%x resid=%ld status=%x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)pkt, xp->target_num, pkt->pkt_reason,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_state, pkt->pkt_resid, pkt->pkt_scbp[0]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk->state == PMCS_WORK_STATE_ABORTED) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: scsi_pkt 0x%p aborted for PHY %s; work = 0x%p",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)pkt, pptr->path, (void *)pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh aborted = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhout:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dma_unload(pwp, sp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler /*
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler * If the device no longer has a PHY pointer, clear the PHY pointer
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler * from the work structure before we free it. Otherwise, pmcs_pwork
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler * may decrement the ref_count on a PHY that's been freed.
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler */
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler if (xp->phy == NULL) {
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pwrk->phy = NULL;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler }
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler
39cd77a06f56f308333bd7b2d8aae1b1467be113Jesse Butler /*
39cd77a06f56f308333bd7b2d8aae1b1467be113Jesse Butler * We may arrive here due to a command timing out, which in turn
39cd77a06f56f308333bd7b2d8aae1b1467be113Jesse Butler * could be addressed in a different context. So, free the work
39cd77a06f56f308333bd7b2d8aae1b1467be113Jesse Butler * back, but only after confirming it's not already been freed
39cd77a06f56f308333bd7b2d8aae1b1467be113Jesse Butler * elsewhere.
39cd77a06f56f308333bd7b2d8aae1b1467be113Jesse Butler */
3492a3fe3944f9ca1cec72cc39496c7a257b5707Jesse Butler if (pwrk->htag != PMCS_TAG_FREE) {
39cd77a06f56f308333bd7b2d8aae1b1467be113Jesse Butler pmcs_pwork(pwp, pwrk);
39cd77a06f56f308333bd7b2d8aae1b1467be113Jesse Butler }
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister /*
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister * If the device is gone, we only put this command on the completion
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister * queue if the work structure is not marked dead. If it's marked
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister * dead, it will already have been put there.
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->dev_gone) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister if (!dead) {
429adc13c4b769a844f808af172a087750ae2e90Srikanth, Ramana mutex_enter(&xp->aqlock);
429adc13c4b769a844f808af172a087750ae2e90Srikanth, Ramana STAILQ_REMOVE(&xp->aq, sp, pmcs_cmd, cmd_next);
429adc13c4b769a844f808af172a087750ae2e90Srikanth, Ramana mutex_exit(&xp->aqlock);
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pmcs_prt(pwp, PMCS_PRT_DEBUG3, pptr, xp,
429adc13c4b769a844f808af172a087750ae2e90Srikanth, Ramana "%s: Removing cmd 0x%p (htag 0x%x) from aq",
429adc13c4b769a844f808af172a087750ae2e90Srikanth, Ramana __func__, (void *)sp, sp->cmd_tag);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister mutex_enter(&pwp->cq_lock);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister STAILQ_INSERT_TAIL(&pwp->cq, sp, cmd_next);
8f514e743bde41fe7e0ca48510a6d4c40ca51c23David Hollister PMCS_CQ_RUN_LOCKED(pwp);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister mutex_exit(&pwp->cq_lock);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG2, pptr, xp,
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister "%s: Completing command for dead target 0x%p",
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister __func__, (void *)xp);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(xp->actv_cnt > 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (--(xp->actv_cnt) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->draining) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG1, pptr, xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: waking up drain waiters", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_signal(&pwp->drain_cv);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister /*
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister * If the status is other than OK, determine if it's something that
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister * is worth re-attempting enumeration. If so, mark the PHY.
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister */
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister if (sts != PMCOUT_STATUS_OK) {
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister pmcs_status_disposition(pptr, sts);
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister }
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (dead == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#ifdef DEBUG
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_cmd_t *wp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->aqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_FOREACH(wp, &xp->aq, cmd_next) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (wp == sp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(wp != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#else
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->aqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#endif
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pmcs_prt(pwp, PMCS_PRT_DEBUG3, pptr, xp,
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister "%s: Removing cmd 0x%p (htag 0x%x) from aq", __func__,
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister (void *)sp, sp->cmd_tag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_REMOVE(&xp->aq, sp, pmcs_cmd, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (aborted) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Aborted cmd for tgt 0x%p, signaling waiters",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)xp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_signal(&xp->abort_cv);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->aqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If do_ds_recovery is set, we need to initiate device state
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * recovery. In this case, we put this I/O back on the head of
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the wait queue to run again after recovery is complete
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (do_ds_recovery) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_start_dev_state_recovery(xp, pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG1, pptr, xp, "%s: Putting cmd 0x%p "
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "back on wq during recovery for tgt 0x%p", __func__,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh (void *)sp, (void *)xp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->wq_recovery_tail == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_HEAD(&xp->wq, sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If there are other I/Os waiting at the head due to
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * device state recovery, add this one in the right spot
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * to maintain proper order.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_AFTER(&xp->wq, xp->wq_recovery_tail, sp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->wq_recovery_tail = sp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we're not initiating device state recovery and this
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * command was not "dead", put it on the completion queue
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!dead) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_TAIL(&pwp->cq, sp, cmd_next);
8f514e743bde41fe7e0ca48510a6d4c40ca51c23David Hollister PMCS_CQ_RUN_LOCKED(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Run a SATA command (normal reads and writes),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * or block and schedule a SATL interpretation
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * of the command.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with pwrk lock held, returns unlocked.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_SATA_run(pmcs_cmd_t *sp, pmcwork_t *pwrk)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = CMD2PMC(sp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct scsi_pkt *pkt = CMD2PKT(sp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *xp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t cdb_base, asc, tag;
69b2e2313400e7ae0a61f2d7cb0a04ff176dfff6Srikanth Suravajhala uint32_t *ptr, lhtag, iq, nblk, i, mtype;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis_t fis;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh size_t amt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint64_t lba;
69b2e2313400e7ae0a61f2d7cb0a04ff176dfff6Srikanth Suravajhala int sp_pkt_time = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp = pwrk->xp;
3be32c0f0acac4f6258b029f1a27a16a7ec65bb0Jesse Butler ASSERT(xp != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * First, see if this is just a plain read/write command.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If not, we have to queue it up for processing, block
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * any additional commands from coming in, and wake up
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the thread that will process this command.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cdb_base = pkt->pkt_cdbp[0] & 0x1f;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (cdb_base != SCMD_READ && cdb_base != SCMD_WRITE) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG1, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: special SATA cmd %p", __func__, (void *)sp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(xp->phy != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(xp->phy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->special_needed = 1; /* Set the special_needed flag */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_TAIL(&xp->sq, sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_run_sata_special(pwp, xp)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_SATA_RUN);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(xp->phy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (PMCS_WQ_RUN_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "%s: regular cmd", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler if (!xp->assigned) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (PMCS_WQ_RUN_FAIL_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->special_running || xp->special_needed || xp->recover_wait) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_HEAD(&xp->wq, sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * By the time we get here the special
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * commands running or waiting to be run
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * may have come and gone, so kick our
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * worker to run the waiting queues
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * just in case.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (PMCS_WQ_RUN_FAIL_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh lba = xp->capacity;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Extract data length and lba parameters out of the command. The
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * function pmcs_SATA_rwparm returns a non-zero ASC value if the CDB
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * values are considered illegal.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh asc = pmcs_SATA_rwparm(pkt->pkt_cdbp, &nblk, &lba, lba);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (asc) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t sns[18];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(sns, sizeof (sns));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sns[0] = 0xf0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sns[2] = 0x5;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sns[12] = asc;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_latch_status(pwp, sp, STATUS_CHECK, sns, sizeof (sns),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->phy->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_TAIL(&pwp->cq, sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_CQ_RUN_LOCKED(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (PMCS_WQ_RUN_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the command decodes as not moving any data, complete it here.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh amt = nblk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh amt <<= 9;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh amt = pmcs_set_resid(pkt, amt, nblk << 9);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (amt == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_latch_status(pwp, sp, STATUS_GOOD, NULL, 0,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->phy->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_pwork(pwp, pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_TAIL(&pwp->cq, sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_CQ_RUN_LOCKED(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (PMCS_WQ_RUN_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Get an inbound queue entry for this I/O
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh GET_IO_IQ_ENTRY(pwp, ptr, xp->phy->device_id, iq);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ptr == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This is a temporary failure not likely to unblocked by
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * commands completing as the test for scheduling the
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * restart of work is a per-device test.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_HEAD(&xp->wq, sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dma_unload(pwp, sp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Failed to get IO IQ entry for tgt %d",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, xp->target_num);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (PMCS_WQ_RUN_FAIL_RES);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Get a tag. At this point, hold statlock until the tagmap is
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * updated (just prior to sending the cmd to the hardware).
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (tag = 0; tag < xp->qdepth; tag++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((xp->tagmap & (1 << tag)) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tag == xp->qdepth) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[iq]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_HEAD(&xp->wq, sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (PMCS_WQ_RUN_FAIL_OTHER);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sp->cmd_satltag = (uint8_t)tag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Set up the command
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bzero(fis, sizeof (fis));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr[0] =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh LE_32(PMCS_IOMB_IN_SAS(PMCS_OQ_IODONE, PMCIN_SATA_HOST_IO_START));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr[1] = LE_32(pwrk->htag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr[2] = LE_32(pwrk->phy->device_id);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr[3] = LE_32(amt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->ncq) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mtype = SATA_PROTOCOL_FPDMA | (tag << 16);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis[0] = ((nblk & 0xff) << 24) | (C_BIT << 8) | FIS_REG_H2DEV;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (cdb_base == SCMD_READ) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis[0] |= (READ_FPDMA_QUEUED << 16);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis[0] |= (WRITE_FPDMA_QUEUED << 16);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis[1] = (FEATURE_LBA << 24) | (lba & 0xffffff);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis[2] = ((nblk & 0xff00) << 16) | ((lba >> 24) & 0xffffff);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis[3] = tag << 3;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int op;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis[0] = (C_BIT << 8) | FIS_REG_H2DEV;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->pio) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mtype = SATA_PROTOCOL_PIO;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (cdb_base == SCMD_READ) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh op = READ_SECTORS_EXT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh op = WRITE_SECTORS_EXT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mtype = SATA_PROTOCOL_DMA;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (cdb_base == SCMD_READ) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh op = READ_DMA_EXT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh op = WRITE_DMA_EXT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis[0] |= (op << 16);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis[1] = (FEATURE_LBA << 24) | (lba & 0xffffff);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis[2] = (lba >> 24) & 0xffffff;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis[3] = nblk;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (cdb_base == SCMD_READ) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr[4] = LE_32(mtype | PMCIN_DATADIR_2_INI);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr[4] = LE_32(mtype | PMCIN_DATADIR_2_DEV);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#ifdef DEBUG
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Generate a PMCOUT_STATUS_XFER_CMD_FRAME_ISSUED
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * event when this goes out on the wire.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr[4] |= PMCIN_MESSAGE_REPORT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#endif
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < (sizeof (fis_t))/(sizeof (uint32_t)); i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ptr[i+5] = LE_32(fis[i]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_dma_load(pwp, sp, ptr)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->iqp_lock[iq]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->wqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_HEAD(&xp->wq, sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->wqlock);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Failed to dma_load for tgt %d",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, xp->target_num);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (PMCS_WQ_RUN_FAIL_RES);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
69b2e2313400e7ae0a61f2d7cb0a04ff176dfff6Srikanth Suravajhala lhtag = pwrk->htag;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->tagmap |= (1 << tag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->actv_cnt++;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->actv_cnt > xp->maxdepth) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->maxdepth = xp->actv_cnt;
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG2, pwrk->phy, xp,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: max depth now %u", pwrk->phy->path, xp->maxdepth);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->aqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_TAIL(&xp->aq, sp, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->aqlock);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: giving pkt %p to hardware", __func__, (void *)pkt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#ifdef DEBUG
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_print_entry(pwp, PMCS_PRT_DEBUG3, "SATA INI Message", ptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#endif
69b2e2313400e7ae0a61f2d7cb0a04ff176dfff6Srikanth Suravajhala sp_pkt_time = CMD2PKT(sp)->pkt_time;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh INC_IQ_ENTRY(pwp, iq);
b53bcbf6c7a28e7236bed3897a3b88444e9e9f7dSrikanth Suravajhala mutex_enter(&pwrk->lock);
69b2e2313400e7ae0a61f2d7cb0a04ff176dfff6Srikanth Suravajhala if (lhtag == pwrk->htag) {
69b2e2313400e7ae0a61f2d7cb0a04ff176dfff6Srikanth Suravajhala pwrk->timer = US2WT(sp_pkt_time * 1000000);
69b2e2313400e7ae0a61f2d7cb0a04ff176dfff6Srikanth Suravajhala if (pwrk->timer == 0) {
69b2e2313400e7ae0a61f2d7cb0a04ff176dfff6Srikanth Suravajhala pwrk->timer = US2WT(1000000);
69b2e2313400e7ae0a61f2d7cb0a04ff176dfff6Srikanth Suravajhala }
b53bcbf6c7a28e7236bed3897a3b88444e9e9f7dSrikanth Suravajhala }
b53bcbf6c7a28e7236bed3897a3b88444e9e9f7dSrikanth Suravajhala mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (PMCS_WQ_RUN_SUCCESS);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Complete a SATA command. Called with pwrk lock held.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_SATA_done(pmcs_hw_t *pwp, pmcwork_t *pwrk, uint32_t *msg)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_cmd_t *sp = pwrk->arg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct scsi_pkt *pkt = CMD2PKT(sp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *pptr = pwrk->phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int dead;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t sts;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *xp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh boolean_t aborted = B_FALSE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp = pwrk->xp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(xp != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DTRACE_PROBE4(pmcs__io__done, uint64_t, pkt->pkt_dma_len, int,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (pkt->pkt_dma_flags & DDI_DMA_READ) != 0, hrtime_t, pwrk->start,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh hrtime_t, gethrtime());
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh dead = pwrk->dead;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (msg) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sts = LE_32(msg[2]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sts = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (dead != 0) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp, "%s: dead cmd tag "
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "0x%x for %s", __func__, pwrk->htag, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((pwrk->state == PMCS_WORK_STATE_TIMED_OUT) &&
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (sts != PMCOUT_STATUS_ABORTED)) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: cmd 0x%p (tag 0x%x) timed out for %s",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)sp, pwrk->htag, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CMD2PKT(sp)->pkt_scbp[0] = STATUS_GOOD;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* pkt_reason already set to CMD_TIMEOUT */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(CMD2PKT(sp)->pkt_reason == CMD_TIMEOUT);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CMD2PKT(sp)->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STATE_SENT_CMD;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CMD2PKT(sp)->pkt_statistics |= STAT_TIMEOUT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG2, pptr, xp, "%s: pkt %p tgt %u done",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)pkt, xp->target_num);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the status isn't okay but not underflow,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * step to the side and parse the (possible) error.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#ifdef DEBUG
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (msg) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_print_entry(pwp, PMCS_PRT_DEBUG3, "Outbound Message", msg);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#endif
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!msg) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh goto out;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the status isn't okay or we got a FIS response of some kind,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * step to the side and parse the (possible) error.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((sts != PMCOUT_STATUS_OK) || (LE_32(msg[3]) != 0)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (sts == PMCOUT_STATUS_IO_DS_NON_OPERATIONAL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((xp->resetting == 0) && (xp->reset_success != 0) &&
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (xp->reset_wait == 0)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pmcs_reset_phy(pwp, pptr,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh PMCS_PHYOP_LINK_RESET) != 0) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: PHY (%s) Local Control/Link "
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "Reset FAILED as part of error "
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "recovery", __func__, pptr->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister pmcs_ioerror(pwp, SATA, pwrk, msg, sts);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_latch_status(pwp, sp, STATUS_GOOD, NULL, 0,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->phy->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_state |= STATE_XFERRED_DATA;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_resid = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG2, pptr, xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: pkt %p tgt %u done reason=%x state=%x resid=%ld status=%x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)pkt, xp->target_num, pkt->pkt_reason,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_state, pkt->pkt_resid, pkt->pkt_scbp[0]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pwrk->state == PMCS_WORK_STATE_ABORTED) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: scsi_pkt 0x%p aborted for PHY %s; work = 0x%p",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)pkt, pptr->path, (void *)pwrk);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh aborted = B_TRUE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhout:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dma_unload(pwp, sp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh xp->tagmap &= ~(1 << sp->cmd_satltag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler /*
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler * If the device no longer has a PHY pointer, clear the PHY pointer
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler * from the work structure before we free it. Otherwise, pmcs_pwork
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler * may decrement the ref_count on a PHY that's been freed.
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler */
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler if (xp->phy == NULL) {
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pwrk->phy = NULL;
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler }
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler
39cd77a06f56f308333bd7b2d8aae1b1467be113Jesse Butler /*
39cd77a06f56f308333bd7b2d8aae1b1467be113Jesse Butler * We may arrive here due to a command timing out, which in turn
39cd77a06f56f308333bd7b2d8aae1b1467be113Jesse Butler * could be addressed in a different context. So, free the work
39cd77a06f56f308333bd7b2d8aae1b1467be113Jesse Butler * back, but only after confirming it's not already been freed
39cd77a06f56f308333bd7b2d8aae1b1467be113Jesse Butler * elsewhere.
39cd77a06f56f308333bd7b2d8aae1b1467be113Jesse Butler */
3492a3fe3944f9ca1cec72cc39496c7a257b5707Jesse Butler if (pwrk->htag != PMCS_TAG_FREE) {
39cd77a06f56f308333bd7b2d8aae1b1467be113Jesse Butler pmcs_pwork(pwp, pwrk);
39cd77a06f56f308333bd7b2d8aae1b1467be113Jesse Butler }
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->dev_gone) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister if (!dead) {
429adc13c4b769a844f808af172a087750ae2e90Srikanth, Ramana mutex_enter(&xp->aqlock);
429adc13c4b769a844f808af172a087750ae2e90Srikanth, Ramana STAILQ_REMOVE(&xp->aq, sp, pmcs_cmd, cmd_next);
429adc13c4b769a844f808af172a087750ae2e90Srikanth, Ramana mutex_exit(&xp->aqlock);
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pmcs_prt(pwp, PMCS_PRT_DEBUG3, pptr, xp,
429adc13c4b769a844f808af172a087750ae2e90Srikanth, Ramana "%s: Removing cmd 0x%p (htag 0x%x) from aq",
429adc13c4b769a844f808af172a087750ae2e90Srikanth, Ramana __func__, (void *)sp, sp->cmd_tag);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister mutex_enter(&pwp->cq_lock);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister STAILQ_INSERT_TAIL(&pwp->cq, sp, cmd_next);
8f514e743bde41fe7e0ca48510a6d4c40ca51c23David Hollister PMCS_CQ_RUN_LOCKED(pwp);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister mutex_exit(&pwp->cq_lock);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG2, pptr, xp,
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister "%s: Completing command for dead target 0x%p",
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister __func__, (void *)xp);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(xp->actv_cnt > 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (--(xp->actv_cnt) == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->draining) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG1, pptr, xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: waking up drain waiters", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_signal(&pwp->drain_cv);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (xp->special_needed) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh SCHEDULE_WORK(pwp, PMCS_WORK_SATA_RUN);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister /*
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister * If the status is other than OK, determine if it's something that
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister * is worth re-attempting enumeration. If so, mark the PHY.
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister */
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister if (sts != PMCOUT_STATUS_OK) {
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister pmcs_status_disposition(pptr, sts);
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister }
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (dead == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#ifdef DEBUG
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_cmd_t *wp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->aqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_FOREACH(wp, &xp->aq, cmd_next) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (wp == sp) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(wp != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#else
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&xp->aqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh#endif
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_REMOVE(&xp->aq, sp, pmcs_cmd, cmd_next);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (aborted) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Aborted cmd for tgt 0x%p, signaling waiters",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, (void *)xp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_signal(&xp->abort_cv);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&xp->aqlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INSERT_TAIL(&pwp->cq, sp, cmd_next);
8f514e743bde41fe7e0ca48510a6d4c40ca51c23David Hollister PMCS_CQ_RUN_LOCKED(pwp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwp->cq_lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic uint8_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_SATA_rwparm(uint8_t *cdb, uint32_t *xfr, uint64_t *lba, uint64_t lbamax)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t asc = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (cdb[0]) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCMD_READ_G5:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCMD_WRITE_G5:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *xfr =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((uint32_t)cdb[10]) << 24) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((uint32_t)cdb[11]) << 16) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((uint32_t)cdb[12]) << 8) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ((uint32_t)cdb[13]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *lba =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((uint64_t)cdb[2]) << 56) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((uint64_t)cdb[3]) << 48) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((uint64_t)cdb[4]) << 40) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((uint64_t)cdb[5]) << 32) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((uint64_t)cdb[6]) << 24) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((uint64_t)cdb[7]) << 16) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((uint64_t)cdb[8]) << 8) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ((uint64_t)cdb[9]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Check for illegal bits */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (cdb[15]) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh asc = 0x24; /* invalid field in cdb */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCMD_READ_G4:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCMD_WRITE_G4:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *xfr =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((uint32_t)cdb[6]) << 16) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((uint32_t)cdb[7]) << 8) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ((uint32_t)cdb[8]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *lba =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((uint32_t)cdb[2]) << 24) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((uint32_t)cdb[3]) << 16) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((uint32_t)cdb[4]) << 8) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ((uint32_t)cdb[5]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Check for illegal bits */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (cdb[11]) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh asc = 0x24; /* invalid field in cdb */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCMD_READ_G1:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCMD_WRITE_G1:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *xfr = (((uint32_t)cdb[7]) << 8) | ((uint32_t)cdb[8]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *lba =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((uint32_t)cdb[2]) << 24) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((uint32_t)cdb[3]) << 16) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((uint32_t)cdb[4]) << 8) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ((uint32_t)cdb[5]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Check for illegal bits */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (cdb[9]) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh asc = 0x24; /* invalid field in cdb */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCMD_READ:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case SCMD_WRITE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *xfr = cdb[4];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (*xfr == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *xfr = 256;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh *lba =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((uint32_t)cdb[1] & 0x1f) << 16) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (((uint32_t)cdb[2]) << 8) |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ((uint32_t)cdb[3]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Check for illegal bits */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (cdb[5]) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh asc = 0x24; /* invalid field in cdb */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (asc == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((*lba + *xfr) > lbamax) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh asc = 0x21; /* logical block out of range */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (asc);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with pwrk lock held.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollisterpmcs_ioerror(pmcs_hw_t *pwp, pmcs_dtype_t t, pmcwork_t *pwrk, uint32_t *w,
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister uint32_t status)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh static uint8_t por[] = {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 0xf0, 0x0, 0x6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x28
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh };
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh static uint8_t parity[] = {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 0xf0, 0x0, 0xb, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x47, 5
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh };
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh const char *msg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char buf[20];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_cmd_t *sp = pwrk->arg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *phyp = pwrk->phy;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct scsi_pkt *pkt = CMD2PKT(sp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint32_t resid;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT(w != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh resid = LE_32(w[3]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg = pmcs_status_str(status);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (msg == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(buf, sizeof (buf), "Error 0x%x", status);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg = buf;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (status != PMCOUT_STATUS_OK) {
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG1, phyp, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: device %s tag 0x%x status %s @ %llu", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp->path, pwrk->htag, msg,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (unsigned long long)gethrtime());
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_reason = CMD_CMPLT; /* default reason */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (status) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OK:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (t == SATA) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int i;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis_t fis;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < sizeof (fis) / sizeof (fis[0]); i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis[i] = LE_32(w[4+i]);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if ((fis[0] & 0xff) != FIS_REG_D2H) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "unexpected fis code 0x%x", fis[0] & 0xff);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "FIS ERROR");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_fis_dump(pwp, fis);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_reason = CMD_TRAN_ERR;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_latch_status(pwp, sp, STATUS_GOOD, NULL, 0, phyp->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_ABORTED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Command successfully aborted.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp->dead) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_reason = CMD_DEV_GONE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_state = STATE_GOT_BUS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (pwrk->ssp_event != 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_reason = CMD_TRAN_ERR;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_state = STATE_GOT_BUS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (pwrk->state == PMCS_WORK_STATE_TIMED_OUT) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_reason = CMD_TIMEOUT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_statistics |= STAT_TIMEOUT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STATE_SENT_CMD;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_reason = CMD_ABORTED;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_statistics |= STAT_ABORTED;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_state = STATE_GOT_BUS | STATE_GOT_TARGET |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STATE_SENT_CMD;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * PMCS_WORK_STATE_TIMED_OUT doesn't need to be preserved past
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * this point, so go ahead and mark it as aborted.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwrk->state = PMCS_WORK_STATE_ABORTED;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_UNDERFLOW:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This will only get called for SATA
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_resid = resid;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (pkt->pkt_dma_len < pkt->pkt_resid) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_set_resid(pkt, pkt->pkt_dma_len, resid);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_latch_status(pwp, sp, STATUS_GOOD, NULL, 0, phyp->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_NO_DEVICE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_SATA_LINK_TIMEOUT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_reason = CMD_DEV_GONE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OPEN_CNX_ERROR_WRONG_DESTINATION:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Need to do rediscovery. We probably have
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the wrong device (disk swap), so kill
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * this one.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OPEN_CNX_PROTOCOL_NOT_SUPPORTED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OPEN_CNX_ERROR_ZONE_VIOLATION:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister case PMCOUT_STATUS_OPEN_CNX_ERROR_UNKNOWN_ERROR:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Need to do rediscovery.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!phyp->dead) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_exit(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_lock_phy(pwrk->phy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_kill_changed(pwp, pwrk->phy, 0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(pwrk->phy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_enter(&pwrk->lock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_reason = CMD_INCOMPLETE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_state = STATE_GOT_BUS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_reason = CMD_DEV_GONE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OPEN_CNX_ERROR_BREAK:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OPENCNX_ERROR_BAD_DESTINATION:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_IO_XFER_ERROR_NAK_RECEIVED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* cmd is pending on the target */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_OFFSET_MISMATCH:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_REJECTED_NCQ_MODE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* transitory - commands sent while in NCQ failure mode */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_ABORTED_NCQ_MODE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* NCQ failure */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_IO_PORT_IN_RESET:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERR_BREAK:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERR_PHY_NOT_READY:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_reason = CMD_INCOMPLETE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_state = STATE_GOT_BUS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_IO_XFER_OPEN_RETRY_TIMEOUT:
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, phyp->target,
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister "STATUS_BUSY for htag 0x%08x", sp->cmd_tag);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_latch_status(pwp, sp, STATUS_BUSY, NULL, 0, phyp->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* synthesize a RESERVATION CONFLICT */
499cfd156ad653fc27397c5f021047c091dd12c5David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, phyp->target,
499cfd156ad653fc27397c5f021047c091dd12c5David Hollister "%s: Potential affiliation active on 0x%" PRIx64, __func__,
499cfd156ad653fc27397c5f021047c091dd12c5David Hollister pmcs_barray2wwn(phyp->sas_address));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_latch_status(pwp, sp, STATUS_RESERVATION_CONFLICT, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh 0, phyp->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_ABORTED_DUE_TO_SRST:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* synthesize a power-on/reset */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_latch_status(pwp, sp, STATUS_CHECK, por, sizeof (por),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_UNEXPECTED_PHASE:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_RDY_OVERRUN:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_RDY_NOT_EXPECTED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_CMD_ISSUE_BREAK_BEFORE_ACK_NACK:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_CMD_ISSUE_PHY_DOWN_BEFORE_ACK_NAK:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* synthesize a PARITY ERROR */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_latch_status(pwp, sp, STATUS_CHECK, parity,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sizeof (parity), phyp->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_IO_XFER_ERROR_DMA:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_IO_NOT_VALID:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_PROG_ERROR:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_PEER_ABORTED:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_XFER_ERROR_SATA: /* non-NCQ failure */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh default:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_reason = CMD_TRAN_ERR;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh break;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Latch up SCSI status
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhvoid
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_latch_status(pmcs_hw_t *pwp, pmcs_cmd_t *sp, uint8_t status,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t *snsp, size_t snslen, char *path)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh static const char c1[] =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Status Byte 0x%02x for CDB0=0x%02x (%02x %02x %02x) "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "HTAG 0x%x @ %llu";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh static const char c2[] =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Status Byte 0x%02x for CDB0=0x%02x HTAG 0x%x @ %llu";
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CMD2PKT(sp)->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STATE_SENT_CMD | STATE_GOT_STATUS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CMD2PKT(sp)->pkt_scbp[0] = status;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (status == STATUS_CHECK && snsp &&
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (size_t)SCSA_STSLEN(sp) >= sizeof (struct scsi_arq_status)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh struct scsi_arq_status *aqp =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *) CMD2PKT(sp)->pkt_scbp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh size_t amt = sizeof (struct scsi_extended_sense);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t key = scsi_sense_key(snsp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t asc = scsi_sense_asc(snsp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint8_t ascq = scsi_sense_ascq(snsp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (amt > snslen) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh amt = snslen;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_SCSI_STATUS, NULL, NULL, c1, path,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh status, CMD2PKT(sp)->pkt_cdbp[0] & 0xff, key, asc, ascq,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sp->cmd_tag, (unsigned long long)gethrtime());
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CMD2PKT(sp)->pkt_state |= STATE_ARQ_DONE;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (*(uint8_t *)&aqp->sts_rqpkt_status) = STATUS_GOOD;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh aqp->sts_rqpkt_statistics = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh aqp->sts_rqpkt_reason = CMD_CMPLT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh aqp->sts_rqpkt_state = STATE_GOT_BUS |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STATE_GOT_TARGET | STATE_SENT_CMD |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STATE_XFERRED_DATA | STATE_GOT_STATUS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(&aqp->sts_sensedata, snsp, amt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (aqp->sts_sensedata.es_class != CLASS_EXTENDED_SENSE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh aqp->sts_rqpkt_reason = CMD_TRAN_ERR;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh aqp->sts_rqpkt_state = 0;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh aqp->sts_rqpkt_resid =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sizeof (struct scsi_extended_sense);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh aqp->sts_rqpkt_resid =
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sizeof (struct scsi_extended_sense) - amt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (status) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_SCSI_STATUS, NULL, NULL, c2,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh path, status, CMD2PKT(sp)->pkt_cdbp[0] & 0xff,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sp->cmd_tag, (unsigned long long)gethrtime());
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CMD2PKT(sp)->pkt_reason = CMD_CMPLT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Calculate and set packet residual and return the amount
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * left over after applying various filters.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhsize_t
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_set_resid(struct scsi_pkt *pkt, size_t amt, uint32_t cdbamt)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pkt->pkt_resid = cdbamt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (amt > pkt->pkt_resid) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh amt = pkt->pkt_resid;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (amt > pkt->pkt_dma_len) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh amt = pkt->pkt_dma_len;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (amt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh/*
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister * Return the existing target softstate (unlocked) if there is one. If so,
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister * the PHY is locked and that lock must be freed by the caller after the
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister * target/PHY linkage is established. If there isn't one, and alloc_tgt is
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister * TRUE, then allocate one.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_xscsi_t *
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butlerpmcs_get_target(pmcs_iport_t *iport, char *tgt_port, boolean_t alloc_tgt)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh{
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_hw_t *pwp = iport->pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_phy_t *phyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_xscsi_t *tgt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh uint64_t wwn;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh char unit_address[PMCS_MAX_UA_SIZE];
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh int ua_form = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Find the PHY for this target
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = pmcs_find_phy_by_sas_address(pwp, iport, NULL, tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp == NULL) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG3, NULL, NULL,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: No PHY for target @ %s", __func__, tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt = ddi_soft_state_bystr_get(iport->tgt_sstate, tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt) {
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister mutex_enter(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * There's already a target. Check its PHY pointer to see
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * if we need to clear the old linkages
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (tgt->phy && (tgt->phy != phyp)) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, phyp, tgt,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Target PHY updated from %p to %p", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)tgt->phy, (void *)phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (!IS_ROOT_PHY(tgt->phy)) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_dec_phy_ref_count(tgt->phy);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_inc_phy_ref_count(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->phy->target = NULL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister /*
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister * If this target has no PHY pointer and alloc_tgt is FALSE,
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister * that implies we expect the target to already exist. This
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister * implies that there has already been a tran_tgt_init on at
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister * least one LU.
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister */
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister if ((tgt->phy == NULL) && !alloc_tgt) {
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, tgt,
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister "%s: Establish linkage from new PHY to old target @"
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister "%s", __func__, tgt->unit_address);
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister for (int idx = 0; idx < tgt->ref_count; idx++) {
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister pmcs_inc_phy_ref_count(phyp);
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister }
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister }
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister
6c87a171a391b9e1c12d8fb7f74466f7e6e637afJesse Butler /*
6c87a171a391b9e1c12d8fb7f74466f7e6e637afJesse Butler * Set this target pointer back up, since it's been
6c87a171a391b9e1c12d8fb7f74466f7e6e637afJesse Butler * through pmcs_clear_xp().
6c87a171a391b9e1c12d8fb7f74466f7e6e637afJesse Butler */
6c87a171a391b9e1c12d8fb7f74466f7e6e637afJesse Butler tgt->dev_gone = 0;
6c87a171a391b9e1c12d8fb7f74466f7e6e637afJesse Butler tgt->assigned = 1;
6c87a171a391b9e1c12d8fb7f74466f7e6e637afJesse Butler tgt->dtype = phyp->dtype;
6c87a171a391b9e1c12d8fb7f74466f7e6e637afJesse Butler tgt->dev_state = PMCS_DEVICE_STATE_OPERATIONAL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->phy = phyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp->target = tgt;
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister mutex_exit(&tgt->statlock);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Make sure the PHY we found is on the correct iport
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp->iport != iport) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: No target at %s on this iport", __func__, tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler /*
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler * If this was just a lookup (i.e. alloc_tgt is false), return now.
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler */
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler if (alloc_tgt == B_FALSE) {
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler pmcs_unlock_phy(phyp);
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler return (NULL);
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler }
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Allocate the new softstate
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh wwn = pmcs_barray2wwn(phyp->sas_address);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) scsi_wwn_to_wwnstr(wwn, ua_form, unit_address);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_soft_state_bystr_zalloc(iport->tgt_sstate, unit_address) !=
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_SUCCESS) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, phyp, tgt,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Couldn't alloc softstate for device at %s",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh __func__, unit_address);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt = ddi_soft_state_bystr_get(iport->tgt_sstate, unit_address);
a25672a1f5bcd6aa4bbce28adab51d84ae202323David Hollister ASSERT(tgt != NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INIT(&tgt->wq);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INIT(&tgt->aq);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh STAILQ_INIT(&tgt->sq);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&tgt->statlock, NULL, MUTEX_DRIVER,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_INTR_PRI(pwp->intr_pri));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&tgt->wqlock, NULL, MUTEX_DRIVER,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_INTR_PRI(pwp->intr_pri));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh mutex_init(&tgt->aqlock, NULL, MUTEX_DRIVER,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DDI_INTR_PRI(pwp->intr_pri));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_init(&tgt->reset_cv, NULL, CV_DRIVER, NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh cv_init(&tgt->abort_cv, NULL, CV_DRIVER, NULL);
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister list_create(&tgt->lun_list, sizeof (pmcs_lun_t),
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister offsetof(pmcs_lun_t, lun_list_next));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->qdepth = 1;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->target_num = PMCS_INVALID_TARGET_NUM;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bcopy(unit_address, tgt->unit_address, PMCS_MAX_UA_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->pwp = pwp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->ua = strdup(iport->ua);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt->phy = phyp;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ASSERT((phyp->target == NULL) || (phyp->target == tgt));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp->target == NULL) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp->target = tgt;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /*
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Don't allocate LUN softstate for SMP targets
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (phyp->dtype == EXPANDER) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_soft_state_bystr_init(&tgt->lun_sstate,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sizeof (pmcs_lun_t), PMCS_LUN_SSTATE_SZ) != 0) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, phyp, tgt,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: LUN soft_state_bystr_init failed", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_bystr_free(iport->tgt_sstate, tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_unlock_phy(phyp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (NULL);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh }
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (tgt);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh}