pmcs_scsa.c revision 5a7797ce9bcfe70ce0ab366abc3051dce3cede6f
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * CDDL HEADER START
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 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * See the License for the specific language governing permissions
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * and limitations under the License.
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 * CDDL HEADER END
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * SCSI (SCSA) midlayer interface for PMC drier.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_scsa_tran_tgt_init(dev_info_t *, dev_info_t *,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void pmcs_scsa_tran_tgt_free(dev_info_t *, dev_info_t *,
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_scsi_reset_notify(struct scsi_address *, int,
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);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Hornestatic int pmcs_smp_init(dev_info_t *, dev_info_t *, smp_hba_tran_t *,
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Hornestatic void pmcs_smp_free(dev_info_t *, dev_info_t *, smp_hba_tran_t *,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic int pmcs_cap(struct scsi_address *, char *, int, int, int);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_addr2xp(struct scsi_address *, uint64_t *, pmcs_cmd_t *);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void pmcs_SAS_done(pmcs_hw_t *, pmcwork_t *, uint32_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);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void pmcs_ioerror(pmcs_hw_t *, pmcs_dtype_t pmcs_dtype,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) memcpy(&pmcs_scsa_dattr, ap, sizeof (ddi_dma_attr_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ((PMCS_SGL_NCHUNKS - 1) * (PMCS_MAX_CHUNKS - 1)) + PMCS_SGL_NCHUNKS;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_scsa_dattr.dma_attr_flags = DDI_DMA_RELAXED_ORDERING;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Allocate a transport structure
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "scsi_hba_tran_alloc failed");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Attach this instance of the hba
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh flags = SCSI_HBA_TRAN_SCB | SCSI_HBA_TRAN_CDB | SCSI_HBA_ADDR_COMPLEX |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (scsi_hba_attach_setup(pwp->dip, &pmcs_scsa_dattr, tran, flags)) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "scsi_hba_attach failed");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Attach the SMP part of this hba
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne if (smp_hba_attach_setup(pwp->dip, pwp->smp_tran) != DDI_SUCCESS) {
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne "smp_hba_attach failed");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * SCSA entry points
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsa_tran_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * First, make sure we're an iport and get the pointer to the HBA
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * node's softstate
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(TRAN2PMC(tran), PMCS_PRT_DEBUG_CONFIG, NULL, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: We don't enumerate devices on the HBA node", __func__);
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed * Get the unit-address
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Get the target address
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh rval = scsi_device_prop_lookup_string(sd, SCSI_DEVICE_PROP_PATH,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "Couldn't get target UA");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Validate that this tran_tgt_init is for an active iport.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Got tran_tgt_init on inactive iport for '%s'",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Since we're going to wait for scratch, be sure to acquire it while
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * we're not holding any other locks
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * See if there's already a target softstate. If not, allocate one.
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler tgt = pmcs_get_target(iport, tgt_port, B_TRUE);
188eaed9d5f14c73dfba1cd0dabaa430bdfd4a9aSrikanth Suravajhala pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "%s: "
188eaed9d5f14c73dfba1cd0dabaa430bdfd4a9aSrikanth Suravajhala "No tgt for tgt_port (%s)", __func__, tgt_port);
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed pmcs_prt(pwp, PMCS_PRT_DEBUG2, phyp, tgt, "@%s tgt = 0x%p, dip = 0x%p",
c40ba10d39e7750947725517ec5639ef2d6e90e5Reed /* Now get the lun */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh lun_num = scsi_device_prop_get_int64(sd, SCSI_DEVICE_PROP_PATH,
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 /* We don't support SATA devices at LUN > 0. */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: No support for SATA devices at LUN > 0 "
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 if (ddi_soft_state_bystr_zalloc(tgt->lun_sstate, ua) != DDI_SUCCESS) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Couldn't allocate LU soft state");
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "Couldn't get LU soft state");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* convert the scsi_lun64_t value to SCSI standard form */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bcopy(ua, lun->unit_address, strnlen(ua, PMCS_MAX_UA_SIZE - 1));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If this is the first tran_tgt_init, add this target to our list
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Target list full.");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: pmcs_assign_device failed for target 0x%p",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) scsi_device_prop_update_int(sd, SCSI_DEVICE_PROP_PATH,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* SM-HBA */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* TCR in PSARC/1997/281 opinion */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) scsi_device_prop_update_int(sd, SCSI_DEVICE_PROP_PATH,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* SM-HBA */
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.
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister pmcs_update_phy_pm_props(phyp, 0, 0, B_TRUE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * phyp's ref count was incremented in pmcs_new_tport.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * We're failing configuration, we now need to decrement it.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh scsi_device_prop_free(sd, SCSI_DEVICE_PROP_PATH, tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsa_tran_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: We don't enumerate devices on the HBA node", __func__);
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 ddi_soft_state_bystr_free(lun->target->lun_sstate, unit_address);
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",
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 * 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 "%s: Free target 0x%p (vtgt %d)", __func__, (void *)target,
6c87a171a391b9e1c12d8fb7f74466f7e6e637afJesse Butler /* If the PHY has a pointer to this target, clear it */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsa_start(struct scsi_address *ap, struct scsi_pkt *pkt)
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: pkt %p sd %p cdb0=0x%02x dl=%lu", __func__, (void *)pkt,
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler * First, check to see if the device is gone.
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler "%s: dropping due to dead target 0x%p",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we're blocked (quiesced) just return.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we're draining or resetting, queue and return.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: draining/resetting/recovering (cnt %u)",
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 * Queue this command to the tail of the wait queue.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This keeps us getting commands out of order.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Now run the queue for this device.
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana/* Return code 1 = Success */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsa_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana scsi_device_hba_private_get(scsi_address_device(ap));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
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 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, xp, "%s: pkt is "
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana "NULL. No tgt/phy to do ABORT_ALL", __func__);
02b04f6e56ca306b4945eca969f282cfe6999414Srikanth, Ramana SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * See if we have a real work structure associated with this cmd.
978d7443a924cda8208d6a10e72be89383bc7becSrikanth Suravajhala pwrk = pmcs_tag2wp(pwp, sp->cmd_tag, B_FALSE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * XXX: Was the command that was active an
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * NCQ I/O command?
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Okay, those weren't the droids we were looking for.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * See if the command is on any of the wait queues.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * SCSA reset functions
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (level) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Point lp at lun so that pmcs_addr2xp
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * will fill out the 64 bit lun number.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* FALLTHROUGH */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)xp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we're already performing this action, or if device
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * state recovery is already running, just return failure.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (scsi_hba_reset_notify_setup(ap, flag, callback, arg,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_cap(struct scsi_address *ap, char *cap, int val, int tonly, int set)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (cidx) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (set == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (set == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (set == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (set == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: cap %s val %d set %d rval %d",
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.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_addr2xp(struct scsi_address *ap, uint64_t *lp, pmcs_cmd_t *sp)
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.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (xp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsa_getcap(struct scsi_address *ap, char *cap, int whom)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (r);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsa_setcap(struct scsi_address *ap, char *cap, int value, int whom)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (r);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_scsa_setup_pkt(struct scsi_pkt *pkt, int (*callback)(caddr_t),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
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);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne (void) memcpy(pwp->scratch, smp_pkt->smp_pkt_req, reqsz);
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 /* PHY is now locked */
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister if ((pptr->iport == NULL) || !pptr->valid_device_id) {
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, pptr->target,
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister "%s: Can't reach PHY %s", __func__, pptr->path);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_reason = will_retry ? EAGAIN : EBUSY;
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_reason = will_retry ? EAGAIN :EBUSY;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL, PMCIN_SMP_REQUEST));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh msg[3] = LE_32(SMP_INDIRECT_RESPONSE | SMP_INDIRECT_REQUEST);
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne WAIT_FOR(pwrk, smp_pkt->smp_pkt_timeout * 1000, result);
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, pptr->target,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Unable to issue SMP ABORT for htag 0x%08x",
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, pptr->target,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Issuing SMP ABORT for htag 0x%08x",
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, pptr->target,
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, pptr->target,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (status ==
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, xp->phy,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Tgt(0x%p) dev_state set to "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)xp);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* ABORT any pending commands related to this device */
96c4a178a18cd52ee5001195f1552d9cef0c38f0Chris Horne smp_pkt->smp_pkt_reason = will_retry ? EAGAIN : EIO;
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG1, pptr, pptr->target,
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister "%s: done for wwn 0x%" PRIx64, __func__, wwn);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Get "target-port" prop from devinfo node */
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "%s: Failed to "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Dont fail _smp_init() because we couldnt get/set a prop */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Validate that this tran_tgt_init is for an active iport.
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: Init on inactive iport for '%s'", __func__, tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Retrieve softstate using unit-address */
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler tgt = pmcs_get_target(iport, tgt_port, B_TRUE);
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, tgt, "%s: %s (%s)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Expander attached to HBA - don't ref_count it */
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 * If this is the 1st smp_init, add this to our list.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "Target list full.");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: pmcs_assign_device failed for target 0x%p",
499cfd156ad653fc27397c5f021047c091dd12c5David Hollister * Update the attached port and target port pm properties
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister pmcs_update_phy_pm_props(phy, 0, 0, B_TRUE);
499cfd156ad653fc27397c5f021047c091dd12c5David Hollister if (smp_device_prop_update_string(smp_sd, SCSI_ADDR_PROP_ATTACHED_PORT,
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "%s: Failed to set "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh ddi_soft_state_bystr_free(iport->tgt_sstate, tgt->unit_address);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Get "target-port" prop from devinfo node */
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "%s: Failed to "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Retrieve softstate using unit-address */
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__,
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 "Removing target 0x%p (vtgt %d) from target list",
6c87a171a391b9e1c12d8fb7f74466f7e6e637afJesse Butler /* If the PHY has a pointer to this target, clear it */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_get_soft_state(pmcs_iport_softstate, ddi_get_instance(dip)))
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0); /* iport */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp = ddi_get_soft_state(pmcs_softc_state, ddi_get_instance(dip));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "%s called", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The pwp->blocked may have been reset. e.g a SCSI bus reset
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (totactive == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_get_soft_state(pmcs_iport_softstate, ddi_get_instance(dip)))
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0); /* iport */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp = ddi_get_soft_state(pmcs_softc_state, ddi_get_instance(dip));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (-1);
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, "%s called", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Run all pending commands.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Complete all completed commands.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * This also unlocks us.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh return (0);
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 * First, check to see if we're blocked or resource limited
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If resource_limited is set, we're resource constrained and
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * we will run only one work request for this target.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Queues will get restarted when we get unblocked */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Might as well verify the queue is not empty before moving on
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we're draining or resetting, just reschedule work queue and bail.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->draining || xp->resetting || xp->special_running ||
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler * Next, check to see if the target is gone.
b18a19c275d2531444fcd2f66664cbe3c6897f6aJesse Butler "%s: Flushing wait queue for dead tgt 0x%p", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void *)xp);
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 * Start commands for all devices.
429adc13c4b769a844f808af172a087750ae2e90Srikanth, Ramana if ((xp == NULL) || (STAILQ_EMPTY(&xp->wq))) {
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister * If we were resource limited, but apparently are not now,
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister * reschedule the work queues anyway.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pwp->resource_limited = 0; /* Not resource-constrained */
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister * Give everybody a chance, and reschedule to run the queues
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister * again as long as we're limited.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Pull the completion queue, drop the lock and complete all elements.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DTRACE_PROBE1(pmcs__scsa__cq__run__start, pmcs_cq_thr_info_t *, cqti);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * First, check the I/O completion callback queue.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Grab the lock on the work structure. The callback
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * routine is responsible for clearing it.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Next, run the completion queue
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh while (sp) {
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 if ((pwp->iocomp_cb_head == NULL) && STAILQ_EMPTY(&pwp->cq) &&
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh DTRACE_PROBE1(pmcs__scsa__cq__run__stop, pmcs_cq_thr_info_t *, cqti);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Run a SAS command. Called with pwrk->lock held, returns unlocked.
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 "%s: Failed to get IO IQ entry for tgt %d",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh LE_32(PMCS_IOMB_IN_SAS(PMCS_OQ_IODONE, PMCIN_SSP_INI_IO_START));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Failed to dma_load for tgt %d (QF)",
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG2, pwrk->phy, xp, "%s: max depth "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Generate a PMCOUT_STATUS_XFER_CMD_FRAME_ISSUED
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * event when this goes out on the wire.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Fill in the SSP IU
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bcopy((uint8_t *)&sp->cmd_lun->scsi_lun, sc.lun, sizeof (scsi_lun_t));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_print_entry(pwp, PMCS_PRT_DEBUG3, "SAS INI Message", ptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If we just submitted the last command queued from device state
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * recovery, clear the wq_recovery_tail pointer.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Complete a SAS command
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with pwrk lock held.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The free of pwrk releases the lock.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_SAS_done(pmcs_hw_t *pwp, pmcwork_t *pwrk, uint32_t *msg)
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 if (dead != 0) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp, "%s: dead cmd tag "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: cmd 0x%p (tag 0x%x) timed out for %s",
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana CMD2PKT(sp)->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET |
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana CMD2PKT(sp)->pkt_statistics |= STAT_TIMEOUT;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the status isn't okay but not underflow,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * step to the side and parse the (possible) error.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_print_entry(pwp, PMCS_PRT_DEBUG3, "Outbound Message", msg);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (sts) {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana "%s: PHY %s requires DS recovery (status=%d)",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) pmcs_set_resid(pkt, pkt->pkt_dma_len, LE_32(msg[3]));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: underflow %u for cdb 0x%x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh const int lim =
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 "Bad SAS RESPONSE DATA LENGTH",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * The only response code we should legally get
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * here is an INVALID FRAME response code.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: pkt %p tgt %u path %s "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "completed: INVALID FRAME response",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: pkt %p tgt %u path %s "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "completed: illegal response 0x%x",
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.
4b4564630e2553df86b078f1fce1624dade2b2cbDavid Hollister * Point residual to the SSP_RESP_IU
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 "residual %d for pkt 0x%p",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: pkt %p tgt %u done reason=%x state=%x resid=%ld status=%x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: scsi_pkt 0x%p aborted for PHY %s; work = 0x%p",
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.
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.
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.
429adc13c4b769a844f808af172a087750ae2e90Srikanth, Ramana STAILQ_REMOVE(&xp->aq, sp, pmcs_cmd, cmd_next);
429adc13c4b769a844f808af172a087750ae2e90Srikanth, Ramana "%s: Removing cmd 0x%p (htag 0x%x) from aq",
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister "%s: Completing command for dead target 0x%p",
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.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (dead == 0) {
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister "%s: Removing cmd 0x%p (htag 0x%x) from aq", __func__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Aborted cmd for tgt 0x%p, signaling waiters",
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
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG1, pptr, xp, "%s: Putting cmd 0x%p "
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 * If we're not initiating device state recovery and this
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * command was not "dead", put it on the completion queue
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Run a SATA command (normal reads and writes),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * or block and schedule a SATL interpretation
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * of the command.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with pwrk lock held, returns unlocked.
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 xp->special_needed = 1; /* Set the special_needed flag */
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG2, NULL, NULL, "%s: regular cmd", __func__);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (xp->special_running || xp->special_needed || xp->recover_wait) {
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 * 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 pmcs_latch_status(pwp, sp, STATUS_CHECK, sns, sizeof (sns),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the command decodes as not moving any data, complete it here.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (amt == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Get an inbound queue entry for this I/O
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 "%s: Failed to get IO IQ entry for tgt %d",
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 * Set up the command
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh LE_32(PMCS_IOMB_IN_SAS(PMCS_OQ_IODONE, PMCIN_SATA_HOST_IO_START));
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis[0] = ((nblk & 0xff) << 24) | (C_BIT << 8) | FIS_REG_H2DEV;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh fis[2] = ((nblk & 0xff00) << 16) | ((lba >> 24) & 0xffffff);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Generate a PMCOUT_STATUS_XFER_CMD_FRAME_ISSUED
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * event when this goes out on the wire.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh for (i = 0; i < (sizeof (fis_t))/(sizeof (uint32_t)); i++) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Failed to dma_load for tgt %d",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_print_entry(pwp, PMCS_PRT_DEBUG3, "SATA INI Message", ptr);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Complete a SATA command. Called with pwrk lock held.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_SATA_done(pmcs_hw_t *pwp, pmcwork_t *pwrk, uint32_t *msg)
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 if (dead != 0) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, xp, "%s: dead cmd tag "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: cmd 0x%p (tag 0x%x) timed out for %s",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* pkt_reason already set to CMD_TIMEOUT */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh CMD2PKT(sp)->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET |
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG2, pptr, xp, "%s: pkt %p tgt %u done",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * If the status isn't okay but not underflow,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * step to the side and parse the (possible) error.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_print_entry(pwp, PMCS_PRT_DEBUG3, "Outbound Message", msg);
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.
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "%s: PHY (%s) Local Control/Link "
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "Reset FAILED as part of error "
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: pkt %p tgt %u done reason=%x state=%x resid=%ld status=%x",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: scsi_pkt 0x%p aborted for PHY %s; work = 0x%p",
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.
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.
429adc13c4b769a844f808af172a087750ae2e90Srikanth, Ramana STAILQ_REMOVE(&xp->aq, sp, pmcs_cmd, cmd_next);
429adc13c4b769a844f808af172a087750ae2e90Srikanth, Ramana "%s: Removing cmd 0x%p (htag 0x%x) from aq",
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister "%s: Completing command for dead target 0x%p",
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.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (dead == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Aborted cmd for tgt 0x%p, signaling waiters",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_SATA_rwparm(uint8_t *cdb, uint32_t *xfr, uint64_t *lba, uint64_t lbamax)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (cdb[0]) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Check for illegal bits */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Check for illegal bits */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Check for illegal bits */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (*xfr == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* Check for illegal bits */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (asc == 0) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Called with pwrk lock held.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhstatic void
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollisterpmcs_ioerror(pmcs_hw_t *pwp, pmcs_dtype_t t, pmcwork_t *pwrk, uint32_t *w,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh const char *msg;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (void) snprintf(buf, sizeof (buf), "Error 0x%x", status);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (unsigned long long)gethrtime());
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh switch (status) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (t == SATA) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh "FIS ERROR");
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_latch_status(pwp, sp, STATUS_GOOD, NULL, 0, phyp->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Command successfully aborted.
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 * This will only get called for SATA
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_latch_status(pwp, sp, STATUS_GOOD, NULL, 0, phyp->path);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Need to do rediscovery. We probably have
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * the wrong device (disk swap), so kill
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * this one.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh case PMCOUT_STATUS_OPEN_CNX_ERROR_CONNECTION_RATE_NOT_SUPPORTED:
9aed162131f1840d0bc1cd0275f4d7144f3690f0David Hollister case PMCOUT_STATUS_OPEN_CNX_ERROR_UNKNOWN_ERROR:
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Need to do rediscovery.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* cmd is pending on the target */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* transitory - commands sent while in NCQ failure mode */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* NCQ failure */
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 /* 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__,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_latch_status(pwp, sp, STATUS_RESERVATION_CONFLICT, NULL,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh /* synthesize a power-on/reset */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh pmcs_latch_status(pwp, sp, STATUS_CHECK, por, sizeof (por),
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 case PMCOUT_STATUS_XFER_ERROR_SATA: /* non-NCQ failure */
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Latch up SCSI status
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_latch_status(pmcs_hw_t *pwp, pmcs_cmd_t *sp, uint8_t status,
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 CMD2PKT(sp)->pkt_state |= STATE_GOT_BUS | STATE_GOT_TARGET |
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh (size_t)SCSA_STSLEN(sp) >= sizeof (struct scsi_arq_status)) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_SCSI_STATUS, NULL, NULL, c1, path,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (aqp->sts_sensedata.es_class != CLASS_EXTENDED_SENSE) {
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh sizeof (struct scsi_extended_sense);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh } else if (status) {
c3bc407cfbd238a18e4728ad5f36f39cecdb062fdh pmcs_prt(pwp, PMCS_PRT_DEBUG_SCSI_STATUS, NULL, NULL, c2,
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Calculate and set packet residual and return the amount
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * left over after applying various filters.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dhpmcs_set_resid(struct scsi_pkt *pkt, size_t amt, uint32_t cdbamt)
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.
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butlerpmcs_get_target(pmcs_iport_t *iport, char *tgt_port, boolean_t alloc_tgt)
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Find the PHY for this target
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh phyp = pmcs_find_phy_by_sas_address(pwp, iport, NULL, tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt = ddi_soft_state_bystr_get(iport->tgt_sstate, tgt_port);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * There's already a target. Check its PHY pointer to see
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * if we need to clear the old linkages
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 "%s: Establish linkage from new PHY to old target @"
c280a92b706bf16eee2a24cc328c9b78d71cb38cDavid Hollister for (int idx = 0; idx < tgt->ref_count; idx++) {
6c87a171a391b9e1c12d8fb7f74466f7e6e637afJesse Butler * Set this target pointer back up, since it's been
6c87a171a391b9e1c12d8fb7f74466f7e6e637afJesse Butler * through pmcs_clear_xp().
6c87a171a391b9e1c12d8fb7f74466f7e6e637afJesse Butler tgt->dev_state = PMCS_DEVICE_STATE_OPERATIONAL;
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Make sure the PHY we found is on the correct iport
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: No target at %s on this iport", __func__, tgt_port);
5c45adf04db8ffdcb5dd969bb5203ff9b17677dbJesse Butler * If this was just a lookup (i.e. alloc_tgt is false), return now.
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Allocate the new softstate
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh if (ddi_soft_state_bystr_zalloc(iport->tgt_sstate, unit_address) !=
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh "%s: Couldn't alloc softstate for device at %s",
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh tgt = ddi_soft_state_bystr_get(iport->tgt_sstate, unit_address);
73a3eccd27d9673a6407274ea0de350699562fd9David Hollister list_create(&tgt->lun_list, sizeof (pmcs_lun_t),
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh bcopy(unit_address, tgt->unit_address, PMCS_MAX_UA_SIZE);
4c06356b0f0fffb4fc1b6eccc8e5d8e2254a84d6dh * Don't allocate LUN softstate for SMP targets