145e0143b4896d03ce53b1af6787afa1a7e73959dh/*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * CDDL HEADER START
145e0143b4896d03ce53b1af6787afa1a7e73959dh *
145e0143b4896d03ce53b1af6787afa1a7e73959dh * The contents of this file are subject to the terms of the
145e0143b4896d03ce53b1af6787afa1a7e73959dh * Common Development and Distribution License (the "License").
145e0143b4896d03ce53b1af6787afa1a7e73959dh * You may not use this file except in compliance with the License.
145e0143b4896d03ce53b1af6787afa1a7e73959dh *
145e0143b4896d03ce53b1af6787afa1a7e73959dh * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
145e0143b4896d03ce53b1af6787afa1a7e73959dh * or http://www.opensolaris.org/os/licensing.
145e0143b4896d03ce53b1af6787afa1a7e73959dh * See the License for the specific language governing permissions
145e0143b4896d03ce53b1af6787afa1a7e73959dh * and limitations under the License.
145e0143b4896d03ce53b1af6787afa1a7e73959dh *
145e0143b4896d03ce53b1af6787afa1a7e73959dh * When distributing Covered Code, include this CDDL HEADER in each
145e0143b4896d03ce53b1af6787afa1a7e73959dh * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
145e0143b4896d03ce53b1af6787afa1a7e73959dh * If applicable, add the following below this CDDL HEADER, with the
145e0143b4896d03ce53b1af6787afa1a7e73959dh * fields enclosed by brackets "[]" replaced with your own identifying
145e0143b4896d03ce53b1af6787afa1a7e73959dh * information: Portions Copyright [yyyy] [name of copyright owner]
145e0143b4896d03ce53b1af6787afa1a7e73959dh *
145e0143b4896d03ce53b1af6787afa1a7e73959dh * CDDL HEADER END
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister */
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister/*
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh/*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * PM8001 device state recovery routines
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh#include <sys/scsi/adapters/pmcs/pmcs.h>
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh/*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * SAS Topology Configuration
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butlerstatic void pmcs_ds_operational(pmcs_phy_t *pptr, pmcs_xscsi_t *tgt);
145e0143b4896d03ce53b1af6787afa1a7e73959dhstatic void pmcs_handle_ds_recovery_error(pmcs_phy_t *phyp,
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pmcs_xscsi_t *tgt, pmcs_hw_t *pwp, const char *func_name,
145e0143b4896d03ce53b1af6787afa1a7e73959dh char *reason_string);
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh/*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * Get device state. Called with statlock and PHY lock held.
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dhstatic int
145e0143b4896d03ce53b1af6787afa1a7e73959dhpmcs_get_dev_state(pmcs_hw_t *pwp, pmcs_phy_t *phyp, pmcs_xscsi_t *xp,
145e0143b4896d03ce53b1af6787afa1a7e73959dh uint8_t *ds)
145e0143b4896d03ce53b1af6787afa1a7e73959dh{
145e0143b4896d03ce53b1af6787afa1a7e73959dh uint32_t htag, *ptr, msg[PMCS_MSG_SIZE];
145e0143b4896d03ce53b1af6787afa1a7e73959dh int result;
145e0143b4896d03ce53b1af6787afa1a7e73959dh struct pmcwork *pwrk;
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG3, phyp, xp, "%s: tgt(0x%p)", __func__,
145e0143b4896d03ce53b1af6787afa1a7e73959dh (void *)xp);
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (xp != NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh ASSERT(mutex_owned(&xp->statlock));
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
f96f3b56078f1646f6c42036086a938c112fbb9fSrikanth, Ramana
f96f3b56078f1646f6c42036086a938c112fbb9fSrikanth, Ramana if (phyp == NULL) {
f96f3b56078f1646f6c42036086a938c112fbb9fSrikanth, Ramana pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, NULL, xp,
f96f3b56078f1646f6c42036086a938c112fbb9fSrikanth, Ramana "%s: PHY is NULL", __func__);
f96f3b56078f1646f6c42036086a938c112fbb9fSrikanth, Ramana return (-1);
f96f3b56078f1646f6c42036086a938c112fbb9fSrikanth, Ramana }
145e0143b4896d03ce53b1af6787afa1a7e73959dh ASSERT(mutex_owned(&phyp->phy_lock));
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, phyp);
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (pwrk == NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_ERR, phyp, xp, pmcs_nowrk, __func__);
145e0143b4896d03ce53b1af6787afa1a7e73959dh return (-1);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh pwrk->arg = msg;
145e0143b4896d03ce53b1af6787afa1a7e73959dh pwrk->dtype = phyp->dtype;
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (phyp->valid_device_id == 0) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_pwork(pwp, pwrk);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, xp,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: Invalid DeviceID", __func__);
145e0143b4896d03ce53b1af6787afa1a7e73959dh return (-1);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh htag = pwrk->htag;
145e0143b4896d03ce53b1af6787afa1a7e73959dh msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
145e0143b4896d03ce53b1af6787afa1a7e73959dh PMCIN_GET_DEVICE_STATE));
145e0143b4896d03ce53b1af6787afa1a7e73959dh msg[1] = LE_32(pwrk->htag);
145e0143b4896d03ce53b1af6787afa1a7e73959dh msg[2] = LE_32(phyp->device_id);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana CLEAN_MESSAGE(msg, 3);
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
145e0143b4896d03ce53b1af6787afa1a7e73959dh ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (ptr == NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_pwork(pwp, pwrk);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_ERR, phyp, xp, pmcs_nomsg, __func__);
145e0143b4896d03ce53b1af6787afa1a7e73959dh return (-1);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh COPY_MESSAGE(ptr, msg, PMCS_MSG_SIZE);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
145e0143b4896d03ce53b1af6787afa1a7e73959dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (xp != NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_exit(&xp->statlock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_unlock_phy(phyp);
145e0143b4896d03ce53b1af6787afa1a7e73959dh WAIT_FOR(pwrk, 1000, result);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_pwork(pwp, pwrk);
3be32c0f0acac4f6258b029f1a27a16a7ec65bb0Jesse Butler pmcs_lock_phy(phyp);
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (xp != NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_enter(&xp->statlock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (result) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_timed_out(pwp, htag, __func__);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, xp,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: cmd timed out, returning", __func__);
145e0143b4896d03ce53b1af6787afa1a7e73959dh return (-1);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (LE_32(msg[2]) == 0) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh *ds = (uint8_t)(LE_32(msg[4]));
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (xp == NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, xp,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: retrieved_ds=0x%x", __func__, *ds);
145e0143b4896d03ce53b1af6787afa1a7e73959dh } else if (*ds != xp->dev_state) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, xp,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: retrieved_ds=0x%x, target_ds=0x%x", __func__,
145e0143b4896d03ce53b1af6787afa1a7e73959dh *ds, xp->dev_state);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh return (0);
145e0143b4896d03ce53b1af6787afa1a7e73959dh } else {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, xp,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: cmd failed Status(0x%x), returning ", __func__,
145e0143b4896d03ce53b1af6787afa1a7e73959dh LE_32(msg[2]));
145e0143b4896d03ce53b1af6787afa1a7e73959dh return (-1);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh}
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh/*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * Set device state. Called with target's statlock and PHY lock held.
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dhstatic int
145e0143b4896d03ce53b1af6787afa1a7e73959dhpmcs_set_dev_state(pmcs_hw_t *pwp, pmcs_phy_t *phyp, pmcs_xscsi_t *xp,
145e0143b4896d03ce53b1af6787afa1a7e73959dh uint8_t ds)
145e0143b4896d03ce53b1af6787afa1a7e73959dh{
145e0143b4896d03ce53b1af6787afa1a7e73959dh uint32_t htag, *ptr, msg[PMCS_MSG_SIZE];
145e0143b4896d03ce53b1af6787afa1a7e73959dh int result;
145e0143b4896d03ce53b1af6787afa1a7e73959dh uint8_t pds, nds;
145e0143b4896d03ce53b1af6787afa1a7e73959dh struct pmcwork *pwrk;
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, xp,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: ds: 0x%x tgt: 0x%p phy: 0x%p", __func__, ds, (void *)xp,
145e0143b4896d03ce53b1af6787afa1a7e73959dh (void *)phyp);
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (phyp == NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, NULL, xp,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: PHY is NULL", __func__);
145e0143b4896d03ce53b1af6787afa1a7e73959dh return (-1);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_WAIT, phyp);
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (pwrk == NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_ERR, phyp, xp, pmcs_nowrk, __func__);
145e0143b4896d03ce53b1af6787afa1a7e73959dh return (-1);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (phyp->valid_device_id == 0) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_pwork(pwp, pwrk);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, xp,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: Invalid DeviceID", __func__);
145e0143b4896d03ce53b1af6787afa1a7e73959dh return (-1);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh pwrk->arg = msg;
145e0143b4896d03ce53b1af6787afa1a7e73959dh pwrk->dtype = phyp->dtype;
145e0143b4896d03ce53b1af6787afa1a7e73959dh htag = pwrk->htag;
145e0143b4896d03ce53b1af6787afa1a7e73959dh msg[0] = LE_32(PMCS_HIPRI(pwp, PMCS_OQ_GENERAL,
145e0143b4896d03ce53b1af6787afa1a7e73959dh PMCIN_SET_DEVICE_STATE));
145e0143b4896d03ce53b1af6787afa1a7e73959dh msg[1] = LE_32(pwrk->htag);
145e0143b4896d03ce53b1af6787afa1a7e73959dh msg[2] = LE_32(phyp->device_id);
145e0143b4896d03ce53b1af6787afa1a7e73959dh msg[3] = LE_32(ds);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana CLEAN_MESSAGE(msg, 4);
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_enter(&pwp->iqp_lock[PMCS_IQ_OTHER]);
145e0143b4896d03ce53b1af6787afa1a7e73959dh ptr = GET_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (ptr == NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_exit(&pwp->iqp_lock[PMCS_IQ_OTHER]);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_pwork(pwp, pwrk);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_ERR, phyp, xp, pmcs_nomsg, __func__);
145e0143b4896d03ce53b1af6787afa1a7e73959dh return (-1);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh COPY_MESSAGE(ptr, msg, PMCS_MSG_SIZE);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pwrk->state = PMCS_WORK_STATE_ONCHIP;
145e0143b4896d03ce53b1af6787afa1a7e73959dh INC_IQ_ENTRY(pwp, PMCS_IQ_OTHER);
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (xp != NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_exit(&xp->statlock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_unlock_phy(phyp);
145e0143b4896d03ce53b1af6787afa1a7e73959dh WAIT_FOR(pwrk, 1000, result);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_pwork(pwp, pwrk);
3be32c0f0acac4f6258b029f1a27a16a7ec65bb0Jesse Butler pmcs_lock_phy(phyp);
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (xp != NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_enter(&xp->statlock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (result) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_timed_out(pwp, htag, __func__);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, xp,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: cmd timed out, returning", __func__);
145e0143b4896d03ce53b1af6787afa1a7e73959dh return (-1);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (LE_32(msg[2]) == 0) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pds = (uint8_t)(LE_32(msg[4]) >> 4);
145e0143b4896d03ce53b1af6787afa1a7e73959dh nds = (uint8_t)(LE_32(msg[4]) & 0x0000000f);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, xp,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: previous_ds=0x%x, new_ds=0x%x", __func__, pds, nds);
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (xp != NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh xp->dev_state = nds;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh return (0);
145e0143b4896d03ce53b1af6787afa1a7e73959dh } else {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, xp,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: cmd failed Status(0x%x), returning ", __func__,
145e0143b4896d03ce53b1af6787afa1a7e73959dh LE_32(msg[2]));
145e0143b4896d03ce53b1af6787afa1a7e73959dh return (-1);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh}
145e0143b4896d03ce53b1af6787afa1a7e73959dh
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butlerstatic void
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butlerpmcs_ds_operational(pmcs_phy_t *pptr, pmcs_xscsi_t *tgt)
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler{
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler pmcs_hw_t *pwp;
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler ASSERT(pptr);
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler pwp = pptr->pwp;
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler if (tgt != NULL) {
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler tgt->recover_wait = 0;
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler }
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler pptr->ds_recovery_retries = 0;
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler if ((pptr->ds_prev_good_recoveries == 0) ||
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler (ddi_get_lbolt() - pptr->last_good_recovery >
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler drv_usectohz(PMCS_MAX_DS_RECOVERY_TIME))) {
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler pptr->last_good_recovery = ddi_get_lbolt();
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler pptr->ds_prev_good_recoveries = 1;
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler } else if (ddi_get_lbolt() < pptr->last_good_recovery +
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler drv_usectohz(PMCS_MAX_DS_RECOVERY_TIME)) {
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler pptr->ds_prev_good_recoveries++;
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler } else {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pmcs_handle_ds_recovery_error(pptr, tgt, pwp, __func__,
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana "Max recovery attempts reached. Declaring PHY dead");
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler }
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler /* Don't bother to run the work queues if the PHY is dead */
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler if (!pptr->dead) {
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES);
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler (void) ddi_taskq_dispatch(pwp->tq, pmcs_worker,
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler pwp, DDI_NOSLEEP);
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler }
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler}
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler
145e0143b4896d03ce53b1af6787afa1a7e73959dhvoid
145e0143b4896d03ce53b1af6787afa1a7e73959dhpmcs_dev_state_recovery(pmcs_hw_t *pwp, pmcs_phy_t *phyp)
145e0143b4896d03ce53b1af6787afa1a7e73959dh{
b0e5d1e5d408b31359b469816fe135bd0b5a5918Srikanth, Ramana boolean_t reschedule = B_FALSE;
145e0143b4896d03ce53b1af6787afa1a7e73959dh uint8_t ds, tgt_dev_state;
145e0143b4896d03ce53b1af6787afa1a7e73959dh int rc;
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_xscsi_t *tgt;
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_phy_t *pptr, *pnext, *pchild;
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh /*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * First time, check to see if we're already performing recovery
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (phyp == NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_enter(&pwp->lock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (pwp->ds_err_recovering) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_exit(&pwp->lock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh SCHEDULE_WORK(pwp, PMCS_WORK_DS_ERR_RECOVERY);
145e0143b4896d03ce53b1af6787afa1a7e73959dh return;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh pwp->ds_err_recovering = 1;
145e0143b4896d03ce53b1af6787afa1a7e73959dh pptr = pwp->root_phys;
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_exit(&pwp->lock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh } else {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pptr = phyp;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh while (pptr) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh /*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * Since ds_err_recovering is set, we can be assured these
145e0143b4896d03ce53b1af6787afa1a7e73959dh * PHYs won't disappear on us while we do this.
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_lock_phy(pptr);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pchild = pptr->children;
145e0143b4896d03ce53b1af6787afa1a7e73959dh pnext = pptr->sibling;
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_unlock_phy(pptr);
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (pchild) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_dev_state_recovery(pwp, pchild);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh tgt = NULL;
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_lock_phy(pptr);
145e0143b4896d03ce53b1af6787afa1a7e73959dh
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana if (pptr->dead || !pptr->valid_device_id) {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana goto next_phy;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana }
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana if (pptr->iport && (pptr->iport->ua_state != UA_ACTIVE)) {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, pptr->target,
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana "%s: No DS recovery on PHY %s, iport not active",
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana __func__, pptr->path);
145e0143b4896d03ce53b1af6787afa1a7e73959dh goto next_phy;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh tgt = pptr->target;
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (tgt != NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_enter(&tgt->statlock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (tgt->recover_wait == 0) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh goto next_phy;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh tgt_dev_state = tgt->dev_state;
145e0143b4896d03ce53b1af6787afa1a7e73959dh } else {
145e0143b4896d03ce53b1af6787afa1a7e73959dh tgt_dev_state = PMCS_DEVICE_STATE_NOT_AVAILABLE;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (pptr->prev_recovery) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (ddi_get_lbolt() - pptr->prev_recovery <
145e0143b4896d03ce53b1af6787afa1a7e73959dh drv_usectohz(PMCS_DS_RECOVERY_INTERVAL)) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG2, pptr, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: DS recovery on PHY %s "
145e0143b4896d03ce53b1af6787afa1a7e73959dh "re-invoked too soon. Skipping...",
145e0143b4896d03ce53b1af6787afa1a7e73959dh __func__, pptr->path);
b0e5d1e5d408b31359b469816fe135bd0b5a5918Srikanth, Ramana if ((tgt) && (tgt->recover_wait)) {
b0e5d1e5d408b31359b469816fe135bd0b5a5918Srikanth, Ramana reschedule = B_TRUE;
b0e5d1e5d408b31359b469816fe135bd0b5a5918Srikanth, Ramana }
145e0143b4896d03ce53b1af6787afa1a7e73959dh goto next_phy;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh pptr->prev_recovery = ddi_get_lbolt();
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh /*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * Step 1: Put the device into the IN_RECOVERY state
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dh rc = pmcs_get_dev_state(pwp, pptr, tgt, &ds);
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (rc != 0) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: pmcs_get_dev_state on PHY %s "
145e0143b4896d03ce53b1af6787afa1a7e73959dh "failed (rc=%d)",
145e0143b4896d03ce53b1af6787afa1a7e73959dh __func__, pptr->path, rc);
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_handle_ds_recovery_error(pptr, tgt, pwp,
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana __func__, "pmcs_get_dev_state");
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh goto next_phy;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler /* If the chip says it's operational, we're done */
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler if (ds == PMCS_DEVICE_STATE_OPERATIONAL) {
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler pmcs_ds_operational(pptr, tgt);
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler goto next_phy;
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler }
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler
145e0143b4896d03ce53b1af6787afa1a7e73959dh if ((tgt_dev_state == ds) &&
145e0143b4896d03ce53b1af6787afa1a7e73959dh (ds == PMCS_DEVICE_STATE_IN_RECOVERY)) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, pptr, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: Target 0x%p already IN_RECOVERY", __func__,
145e0143b4896d03ce53b1af6787afa1a7e73959dh (void *)tgt);
145e0143b4896d03ce53b1af6787afa1a7e73959dh } else {
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (tgt != NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh tgt->dev_state = ds;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh tgt_dev_state = ds;
145e0143b4896d03ce53b1af6787afa1a7e73959dh ds = PMCS_DEVICE_STATE_IN_RECOVERY;
145e0143b4896d03ce53b1af6787afa1a7e73959dh rc = pmcs_send_err_recovery_cmd(pwp, ds, pptr, tgt);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, pptr, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: pmcs_send_err_recovery_cmd "
145e0143b4896d03ce53b1af6787afa1a7e73959dh "result(%d) tgt(0x%p) ds(0x%x) tgt->ds(0x%x)",
145e0143b4896d03ce53b1af6787afa1a7e73959dh __func__, rc, (void *)tgt, ds, tgt_dev_state);
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (rc) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: pmcs_send_err_recovery_cmd to PHY %s "
145e0143b4896d03ce53b1af6787afa1a7e73959dh "failed (rc=%d)",
145e0143b4896d03ce53b1af6787afa1a7e73959dh __func__, pptr->path, rc);
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_handle_ds_recovery_error(pptr, tgt, pwp,
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana __func__, "pmcs_send_err_recovery_cmd");
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh goto next_phy;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh /*
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler * Step 2: Perform a hard reset on the PHY.
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, pptr, tgt,
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana "%s: Issue HARD_RESET to PHY %s", __func__,
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pptr->path);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana /*
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana * Must release statlock here because pmcs_reset_phy
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana * will drop and reacquire the PHY lock.
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana */
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana if (tgt != NULL) {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana mutex_exit(&tgt->statlock);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana }
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana rc = pmcs_reset_phy(pwp, pptr, PMCS_PHYOP_HARD_RESET);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana if (tgt != NULL) {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana mutex_enter(&tgt->statlock);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana }
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana if (rc) {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana "%s: HARD_RESET to PHY %s failed (rc=%d)",
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana __func__, pptr->path, rc);
145e0143b4896d03ce53b1af6787afa1a7e73959dh
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pmcs_handle_ds_recovery_error(pptr, tgt, pwp,
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana __func__, "HARD_RESET");
145e0143b4896d03ce53b1af6787afa1a7e73959dh
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana goto next_phy;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh /*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * Step 3: Abort all I/Os to the device
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (pptr->abort_all_start) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh while (pptr->abort_all_start) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: Waiting for outstanding ABORT_ALL on "
145e0143b4896d03ce53b1af6787afa1a7e73959dh "PHY 0x%p", __func__, (void *)pptr);
145e0143b4896d03ce53b1af6787afa1a7e73959dh cv_wait(&pptr->abort_all_cv, &pptr->phy_lock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh } else {
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (tgt != NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_exit(&tgt->statlock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh rc = pmcs_abort(pwp, pptr, pptr->device_id, 1, 1);
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (tgt != NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_enter(&tgt->statlock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (rc != 0) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pptr->abort_pending = 1;
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: pmcs_abort to PHY %s failed (rc=%d)",
145e0143b4896d03ce53b1af6787afa1a7e73959dh __func__, pptr->path, rc);
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_handle_ds_recovery_error(pptr, tgt,
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pwp, __func__, "pmcs_abort");
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh goto next_phy;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh /*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * Step 4: Set the device back to OPERATIONAL state
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, pptr, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: Set PHY/tgt 0x%p/0x%p to OPERATIONAL state",
145e0143b4896d03ce53b1af6787afa1a7e73959dh __func__, (void *)pptr, (void *)tgt);
145e0143b4896d03ce53b1af6787afa1a7e73959dh rc = pmcs_set_dev_state(pwp, pptr, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh PMCS_DEVICE_STATE_OPERATIONAL);
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (rc == 0) {
6745c559e4b531cf336a91f4653445c32ee46693Jesse Butler pmcs_ds_operational(pptr, tgt);
145e0143b4896d03ce53b1af6787afa1a7e73959dh } else {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, pptr, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: Failed to SET tgt 0x%p to OPERATIONAL state",
145e0143b4896d03ce53b1af6787afa1a7e73959dh __func__, (void *)tgt);
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_handle_ds_recovery_error(pptr, tgt, pwp,
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana __func__, "SET tgt to OPERATIONAL state");
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh goto next_phy;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dhnext_phy:
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (tgt) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_exit(&tgt->statlock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_unlock_phy(pptr);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pptr = pnext;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh /*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * Only clear ds_err_recovering if we're exiting for good and not
145e0143b4896d03ce53b1af6787afa1a7e73959dh * just unwinding from recursion
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (phyp == NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_enter(&pwp->lock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pwp->ds_err_recovering = 0;
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_exit(&pwp->lock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
b0e5d1e5d408b31359b469816fe135bd0b5a5918Srikanth, Ramana
b0e5d1e5d408b31359b469816fe135bd0b5a5918Srikanth, Ramana if (reschedule) {
b0e5d1e5d408b31359b469816fe135bd0b5a5918Srikanth, Ramana SCHEDULE_WORK(pwp, PMCS_WORK_DS_ERR_RECOVERY);
b0e5d1e5d408b31359b469816fe135bd0b5a5918Srikanth, Ramana }
145e0143b4896d03ce53b1af6787afa1a7e73959dh}
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh/*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * Called with target's statlock held (if target is non-NULL) and PHY lock held.
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dhint
145e0143b4896d03ce53b1af6787afa1a7e73959dhpmcs_send_err_recovery_cmd(pmcs_hw_t *pwp, uint8_t dev_state, pmcs_phy_t *phyp,
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_xscsi_t *tgt)
145e0143b4896d03ce53b1af6787afa1a7e73959dh{
145e0143b4896d03ce53b1af6787afa1a7e73959dh int rc = -1;
145e0143b4896d03ce53b1af6787afa1a7e73959dh uint8_t tgt_dev_state = PMCS_DEVICE_STATE_NOT_AVAILABLE;
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (tgt != NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh ASSERT(mutex_owned(&tgt->statlock));
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (tgt->recovering) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh return (0);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh tgt->recovering = 1;
145e0143b4896d03ce53b1af6787afa1a7e73959dh tgt_dev_state = tgt->dev_state;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (phyp == NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, NULL, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: PHY is NULL", __func__);
145e0143b4896d03ce53b1af6787afa1a7e73959dh return (-1);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh ASSERT(mutex_owned(&phyp->phy_lock));
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: ds: 0x%x, tgt ds(0x%x)", __func__, dev_state, tgt_dev_state);
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh switch (dev_state) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh case PMCS_DEVICE_STATE_IN_RECOVERY:
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (tgt_dev_state == PMCS_DEVICE_STATE_IN_RECOVERY) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: Target 0x%p already IN_RECOVERY", __func__,
145e0143b4896d03ce53b1af6787afa1a7e73959dh (void *)tgt);
145e0143b4896d03ce53b1af6787afa1a7e73959dh rc = 0; /* This is not an error */
145e0143b4896d03ce53b1af6787afa1a7e73959dh goto no_action;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh rc = pmcs_set_dev_state(pwp, phyp, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh PMCS_DEVICE_STATE_IN_RECOVERY);
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (rc != 0) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s(1): Failed to set tgt(0x%p) to IN_RECOVERY",
145e0143b4896d03ce53b1af6787afa1a7e73959dh __func__, (void *)tgt);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh break;
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh case PMCS_DEVICE_STATE_OPERATIONAL:
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (tgt_dev_state != PMCS_DEVICE_STATE_IN_RECOVERY) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: Target 0x%p not ready to go OPERATIONAL",
145e0143b4896d03ce53b1af6787afa1a7e73959dh __func__, (void *)tgt);
145e0143b4896d03ce53b1af6787afa1a7e73959dh goto no_action;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh rc = pmcs_set_dev_state(pwp, phyp, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh PMCS_DEVICE_STATE_OPERATIONAL);
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (tgt != NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh tgt->reset_success = 1;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (rc != 0) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s(2): Failed to SET tgt(0x%p) to OPERATIONAL",
145e0143b4896d03ce53b1af6787afa1a7e73959dh __func__, (void *)tgt);
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (tgt != NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh tgt->reset_success = 0;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh break;
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh case PMCS_DEVICE_STATE_NON_OPERATIONAL:
145e0143b4896d03ce53b1af6787afa1a7e73959dh PHY_CHANGED(pwp, phyp);
145e0143b4896d03ce53b1af6787afa1a7e73959dh RESTART_DISCOVERY(pwp);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: Device at %s is non-operational",
145e0143b4896d03ce53b1af6787afa1a7e73959dh __func__, phyp->path);
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (tgt != NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh tgt->dev_state = PMCS_DEVICE_STATE_NON_OPERATIONAL;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh rc = 0;
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh break;
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh default:
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: Invalid state requested (%d)", __func__,
145e0143b4896d03ce53b1af6787afa1a7e73959dh dev_state);
145e0143b4896d03ce53b1af6787afa1a7e73959dh break;
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dhno_action:
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (tgt != NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh tgt->recovering = 0;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh return (rc);
145e0143b4896d03ce53b1af6787afa1a7e73959dh}
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh/*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * Start ssp event recovery. We have to schedule recovery operation because
145e0143b4896d03ce53b1af6787afa1a7e73959dh * it involves sending multiple commands to device and we should not do it
145e0143b4896d03ce53b1af6787afa1a7e73959dh * in the interrupt context.
145e0143b4896d03ce53b1af6787afa1a7e73959dh * If it is failure of a recovery command, let the recovery thread deal with it.
225bf9057f97461ac410ec2e1432d1575360ee18Jesse Butler * Called with the work lock held.
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dhvoid
145e0143b4896d03ce53b1af6787afa1a7e73959dhpmcs_start_ssp_event_recovery(pmcs_hw_t *pwp, pmcwork_t *pwrk, uint32_t *iomb,
145e0143b4896d03ce53b1af6787afa1a7e73959dh size_t amt)
145e0143b4896d03ce53b1af6787afa1a7e73959dh{
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_xscsi_t *tgt = pwrk->xp;
145e0143b4896d03ce53b1af6787afa1a7e73959dh uint32_t event = LE_32(iomb[2]);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_phy_t *pptr = pwrk->phy;
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister pmcs_cb_t callback;
145e0143b4896d03ce53b1af6787afa1a7e73959dh uint32_t tag;
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (tgt != NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_enter(&tgt->statlock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (!tgt->assigned) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (pptr) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_dec_phy_ref_count(pptr);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh pptr = NULL;
145e0143b4896d03ce53b1af6787afa1a7e73959dh pwrk->phy = NULL;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_exit(&tgt->statlock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
56976565c7cea0f2fbde67ea3a985d8b17a71288David Hollister
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (pptr == NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh /*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * No target, need to run RE-DISCOVERY here.
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (pwrk->state != PMCS_WORK_STATE_TIMED_OUT) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pwrk->state = PMCS_WORK_STATE_INTR;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh /*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * Although we cannot mark phy to force abort nor mark phy
145e0143b4896d03ce53b1af6787afa1a7e73959dh * as changed, killing of a target would take care of aborting
145e0143b4896d03ce53b1af6787afa1a7e73959dh * commands for the device.
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: No valid target for event processing. Reconfigure.",
145e0143b4896d03ce53b1af6787afa1a7e73959dh __func__);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_pwork(pwp, pwrk);
145e0143b4896d03ce53b1af6787afa1a7e73959dh RESTART_DISCOVERY(pwp);
145e0143b4896d03ce53b1af6787afa1a7e73959dh return;
145e0143b4896d03ce53b1af6787afa1a7e73959dh } else {
225bf9057f97461ac410ec2e1432d1575360ee18Jesse Butler /* We have a phy pointer, we'll need to lock it */
225bf9057f97461ac410ec2e1432d1575360ee18Jesse Butler mutex_exit(&pwrk->lock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_lock_phy(pptr);
225bf9057f97461ac410ec2e1432d1575360ee18Jesse Butler mutex_enter(&pwrk->lock);
3be32c0f0acac4f6258b029f1a27a16a7ec65bb0Jesse Butler if (tgt != NULL) {
56976565c7cea0f2fbde67ea3a985d8b17a71288David Hollister mutex_enter(&tgt->statlock);
56976565c7cea0f2fbde67ea3a985d8b17a71288David Hollister }
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (event == PMCOUT_STATUS_OPEN_CNX_ERROR_IT_NEXUS_LOSS) {
3be32c0f0acac4f6258b029f1a27a16a7ec65bb0Jesse Butler if ((tgt != NULL) && (tgt->dev_state !=
3be32c0f0acac4f6258b029f1a27a16a7ec65bb0Jesse Butler PMCS_DEVICE_STATE_NON_OPERATIONAL)) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: Device at %s is non-operational",
145e0143b4896d03ce53b1af6787afa1a7e73959dh __func__, pptr->path);
145e0143b4896d03ce53b1af6787afa1a7e73959dh tgt->dev_state =
145e0143b4896d03ce53b1af6787afa1a7e73959dh PMCS_DEVICE_STATE_NON_OPERATIONAL;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh pptr->abort_pending = 1;
3be32c0f0acac4f6258b029f1a27a16a7ec65bb0Jesse Butler if (tgt != NULL) {
56976565c7cea0f2fbde67ea3a985d8b17a71288David Hollister mutex_exit(&tgt->statlock);
56976565c7cea0f2fbde67ea3a985d8b17a71288David Hollister }
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_exit(&pwrk->lock);
225bf9057f97461ac410ec2e1432d1575360ee18Jesse Butler pmcs_unlock_phy(pptr);
145e0143b4896d03ce53b1af6787afa1a7e73959dh SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE);
145e0143b4896d03ce53b1af6787afa1a7e73959dh RESTART_DISCOVERY(pwp);
145e0143b4896d03ce53b1af6787afa1a7e73959dh return;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh /*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * If this command is run in WAIT mode, it is a failing recovery
145e0143b4896d03ce53b1af6787afa1a7e73959dh * command. If so, just wake up recovery thread waiting for
145e0143b4896d03ce53b1af6787afa1a7e73959dh * command completion.
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dh tag = PMCS_TAG_TYPE(pwrk->htag);
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (tag == PMCS_TAG_TYPE_WAIT) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pwrk->htag |= PMCS_TAG_DONE;
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (pwrk->arg && amt) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh (void) memcpy(pwrk->arg, iomb, amt);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh cv_signal(&pwrk->sleep_cv);
3be32c0f0acac4f6258b029f1a27a16a7ec65bb0Jesse Butler if (tgt != NULL) {
56976565c7cea0f2fbde67ea3a985d8b17a71288David Hollister mutex_exit(&tgt->statlock);
56976565c7cea0f2fbde67ea3a985d8b17a71288David Hollister }
225bf9057f97461ac410ec2e1432d1575360ee18Jesse Butler mutex_exit(&pwrk->lock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_unlock_phy(pptr);
145e0143b4896d03ce53b1af6787afa1a7e73959dh return;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
3be32c0f0acac4f6258b029f1a27a16a7ec65bb0Jesse Butler if (tgt == NULL) {
56976565c7cea0f2fbde67ea3a985d8b17a71288David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG1, pptr, NULL,
56976565c7cea0f2fbde67ea3a985d8b17a71288David Hollister "%s: Not scheduling SSP event recovery for NULL tgt"
56976565c7cea0f2fbde67ea3a985d8b17a71288David Hollister " pwrk(%p) tag(0x%x)", __func__, (void *)pwrk,
56976565c7cea0f2fbde67ea3a985d8b17a71288David Hollister pwrk->htag);
225bf9057f97461ac410ec2e1432d1575360ee18Jesse Butler mutex_exit(&pwrk->lock);
225bf9057f97461ac410ec2e1432d1575360ee18Jesse Butler pmcs_unlock_phy(pptr);
56976565c7cea0f2fbde67ea3a985d8b17a71288David Hollister return;
56976565c7cea0f2fbde67ea3a985d8b17a71288David Hollister }
56976565c7cea0f2fbde67ea3a985d8b17a71288David Hollister
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister /*
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister * If the SSP event was an OPEN_RETRY_TIMEOUT, we don't want
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister * to go through the recovery (abort/LU reset) process.
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister * Simply complete the command and return it as STATUS_BUSY.
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister * This will cause the target driver to simply retry.
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister */
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister if (event == PMCOUT_STATUS_IO_XFER_OPEN_RETRY_TIMEOUT) {
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister "%s: Got OPEN_RETRY_TIMEOUT event (htag 0x%08x)",
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister __func__, pwrk->htag);
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister mutex_exit(&tgt->statlock);
225bf9057f97461ac410ec2e1432d1575360ee18Jesse Butler /* Note: work remains locked for the callback */
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister pmcs_unlock_phy(pptr);
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister pwrk->ssp_event = event;
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister callback = (pmcs_cb_t)pwrk->ptr;
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister (*callback)(pwp, pwrk, iomb);
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister return;
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister }
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister
145e0143b4896d03ce53b1af6787afa1a7e73959dh /*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * To recover from primary failures,
145e0143b4896d03ce53b1af6787afa1a7e73959dh * we need to schedule handling events recovery.
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dh tgt->event_recovery = 1;
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_exit(&tgt->statlock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pwrk->ssp_event = event;
225bf9057f97461ac410ec2e1432d1575360ee18Jesse Butler mutex_exit(&pwrk->lock);
225bf9057f97461ac410ec2e1432d1575360ee18Jesse Butler pmcs_unlock_phy(pptr);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: Scheduling SSP event recovery for tgt(0x%p) "
145e0143b4896d03ce53b1af6787afa1a7e73959dh "pwrk(%p) tag(0x%x)", __func__, (void *)tgt, (void *)pwrk,
145e0143b4896d03ce53b1af6787afa1a7e73959dh pwrk->htag);
145e0143b4896d03ce53b1af6787afa1a7e73959dh SCHEDULE_WORK(pwp, PMCS_WORK_SSP_EVT_RECOVERY);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh /* Work cannot be completed until event recovery is completed. */
145e0143b4896d03ce53b1af6787afa1a7e73959dh}
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh/*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * SSP target event recovery
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala * phy->lock should be held upon entry.
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala * pwrk->lock should be held upon entry and gets released by this routine.
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala * tgt->statlock should not be held.
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dhvoid
145e0143b4896d03ce53b1af6787afa1a7e73959dhpmcs_tgt_event_recovery(pmcs_hw_t *pwp, pmcwork_t *pwrk)
145e0143b4896d03ce53b1af6787afa1a7e73959dh{
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_phy_t *pptr = pwrk->phy;
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_cmd_t *sp = pwrk->arg;
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_lun_t *lun = sp->cmd_lun;
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_xscsi_t *tgt = pwrk->xp;
145e0143b4896d03ce53b1af6787afa1a7e73959dh uint32_t event;
145e0143b4896d03ce53b1af6787afa1a7e73959dh uint32_t htag;
145e0143b4896d03ce53b1af6787afa1a7e73959dh uint32_t status;
145e0143b4896d03ce53b1af6787afa1a7e73959dh int rv;
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh ASSERT(pwrk->arg != NULL);
145e0143b4896d03ce53b1af6787afa1a7e73959dh ASSERT(pwrk->xp != NULL);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: event recovery for target 0x%p", __func__, (void *)pwrk->xp);
145e0143b4896d03ce53b1af6787afa1a7e73959dh htag = pwrk->htag;
145e0143b4896d03ce53b1af6787afa1a7e73959dh event = pwrk->ssp_event;
145e0143b4896d03ce53b1af6787afa1a7e73959dh pwrk->ssp_event = 0xffffffff;
658280b6253b61dbb155f43d0e3cbcffa85ccb90David Hollister
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala mutex_exit(&pwrk->lock);
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (event == PMCOUT_STATUS_XFER_ERR_BREAK ||
145e0143b4896d03ce53b1af6787afa1a7e73959dh event == PMCOUT_STATUS_XFER_ERR_PHY_NOT_READY ||
145e0143b4896d03ce53b1af6787afa1a7e73959dh event == PMCOUT_STATUS_XFER_ERROR_CMD_ISSUE_ACK_NAK_TIMEOUT) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh /* Command may be still pending on device */
145e0143b4896d03ce53b1af6787afa1a7e73959dh rv = pmcs_ssp_tmf(pwp, pptr, SAS_QUERY_TASK, htag,
145e0143b4896d03ce53b1af6787afa1a7e73959dh lun->lun_num, &status);
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (rv != 0) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh goto out;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (status == SAS_RSP_TMF_COMPLETE) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh /* Command NOT pending on a device */
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: No pending command for tgt 0x%p",
145e0143b4896d03ce53b1af6787afa1a7e73959dh __func__, (void *)tgt);
145e0143b4896d03ce53b1af6787afa1a7e73959dh /* Nothing more to do, just abort it on chip */
145e0143b4896d03ce53b1af6787afa1a7e73959dh htag = 0;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh /*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * All other events left the command pending in the host
145e0143b4896d03ce53b1af6787afa1a7e73959dh * Send abort task and abort it on the chip
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (htag != 0) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (pmcs_ssp_tmf(pwp, pptr, SAS_ABORT_TASK, htag,
145e0143b4896d03ce53b1af6787afa1a7e73959dh lun->lun_num, &status))
145e0143b4896d03ce53b1af6787afa1a7e73959dh goto out;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala (void) pmcs_abort(pwp, pptr, htag, 0, 1);
145e0143b4896d03ce53b1af6787afa1a7e73959dh /*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * Abort either took care of work completion, or put device in
145e0143b4896d03ce53b1af6787afa1a7e73959dh * a recovery state
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dh return;
145e0143b4896d03ce53b1af6787afa1a7e73959dhout:
145e0143b4896d03ce53b1af6787afa1a7e73959dh /* Abort failed, do full device recovery */
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala mutex_enter(&pwrk->lock);
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala tgt = pwrk->xp;
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala mutex_exit(&pwrk->lock);
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala if (tgt != NULL) {
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala mutex_enter(&tgt->statlock);
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala pmcs_start_dev_state_recovery(tgt, pptr);
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala mutex_exit(&tgt->statlock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh}
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh/*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * SSP event recovery task.
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dhvoid
145e0143b4896d03ce53b1af6787afa1a7e73959dhpmcs_ssp_event_recovery(pmcs_hw_t *pwp)
145e0143b4896d03ce53b1af6787afa1a7e73959dh{
145e0143b4896d03ce53b1af6787afa1a7e73959dh int idx;
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_xscsi_t *tgt;
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_cmd_t *cp;
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcwork_t *pwrk;
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_phy_t *pphy;
145e0143b4896d03ce53b1af6787afa1a7e73959dh int er_flag;
145e0143b4896d03ce53b1af6787afa1a7e73959dh uint32_t idxpwrk;
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dhrestart:
145e0143b4896d03ce53b1af6787afa1a7e73959dh for (idx = 0; idx < pwp->max_dev; idx++) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_enter(&pwp->lock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh tgt = pwp->targets[idx];
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_exit(&pwp->lock);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana if (tgt == NULL) {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana continue;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana }
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana mutex_enter(&tgt->statlock);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana if (!tgt->assigned) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_exit(&tgt->statlock);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana continue;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana }
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pphy = tgt->phy;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana er_flag = tgt->event_recovery;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana mutex_exit(&tgt->statlock);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana if ((pphy == NULL) || (er_flag == 0)) {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana continue;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana }
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pmcs_lock_phy(pphy);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pmcs_prt(pwp, PMCS_PRT_DEBUG, pphy, tgt,
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana "%s: found target(0x%p)", __func__, (void *) tgt);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana /* Check what cmd expects recovery */
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana mutex_enter(&tgt->aqlock);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana STAILQ_FOREACH(cp, &tgt->aq, cmd_next) {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana idxpwrk = PMCS_TAG_INDEX(cp->cmd_tag);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pwrk = &pwp->work[idxpwrk];
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala mutex_enter(&pwrk->lock);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana if (pwrk->htag != cp->cmd_tag) {
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana /*
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana * aq may contain TMF commands, so we
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana * may not find work structure with htag
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana */
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala mutex_exit(&pwrk->lock);
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala continue;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana }
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala if (!PMCS_COMMAND_DONE(pwrk) &&
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala (pwrk->ssp_event != 0) &&
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana (pwrk->ssp_event != PMCS_REC_EVENT)) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG, pphy, tgt,
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana "%s: pwrk(%p) htag(0x%x)",
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana __func__, (void *) pwrk, cp->cmd_tag);
145e0143b4896d03ce53b1af6787afa1a7e73959dh mutex_exit(&tgt->aqlock);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana /*
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala * pwrk->lock gets dropped in
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala * pmcs_tgt_event_recovery()
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana */
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala pmcs_tgt_event_recovery(pwp, pwrk);
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_unlock_phy(pphy);
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala /* All bets are off on tgt/aq now, restart */
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana goto restart;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala mutex_exit(&pwrk->lock);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana mutex_exit(&tgt->aqlock);
219ebc8ed9819073f2dd55dead617f876abaa22dSrikanth Suravajhala mutex_enter(&tgt->statlock);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana tgt->event_recovery = 0;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pmcs_prt(pwp, PMCS_PRT_DEBUG, pphy, tgt,
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana "%s: end of SSP event recovery for target(0x%p)",
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana __func__, (void *) tgt);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana mutex_exit(&tgt->statlock);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pmcs_unlock_phy(pphy);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: end of SSP event recovery for pwp(0x%p)", __func__,
145e0143b4896d03ce53b1af6787afa1a7e73959dh (void *) pwp);
145e0143b4896d03ce53b1af6787afa1a7e73959dh}
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dhvoid
145e0143b4896d03ce53b1af6787afa1a7e73959dhpmcs_start_dev_state_recovery(pmcs_xscsi_t *xp, pmcs_phy_t *phyp)
145e0143b4896d03ce53b1af6787afa1a7e73959dh{
145e0143b4896d03ce53b1af6787afa1a7e73959dh ASSERT(mutex_owned(&xp->statlock));
145e0143b4896d03ce53b1af6787afa1a7e73959dh ASSERT(xp->pwp != NULL);
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (xp->recover_wait == 0) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(xp->pwp, PMCS_PRT_DEBUG_DEV_STATE, phyp, xp,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: Start ds_recovery for tgt 0x%p/PHY 0x%p (%s)",
145e0143b4896d03ce53b1af6787afa1a7e73959dh __func__, (void *)xp, (void *)phyp, phyp->path);
145e0143b4896d03ce53b1af6787afa1a7e73959dh xp->recover_wait = 1;
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh /*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * Rather than waiting for the watchdog timer, we'll
145e0143b4896d03ce53b1af6787afa1a7e73959dh * kick it right now.
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dh SCHEDULE_WORK(xp->pwp, PMCS_WORK_DS_ERR_RECOVERY);
145e0143b4896d03ce53b1af6787afa1a7e73959dh (void) ddi_taskq_dispatch(xp->pwp->tq, pmcs_worker, xp->pwp,
145e0143b4896d03ce53b1af6787afa1a7e73959dh DDI_NOSLEEP);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh}
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh/*
145e0143b4896d03ce53b1af6787afa1a7e73959dh * Increment the phy ds error retry count.
145e0143b4896d03ce53b1af6787afa1a7e73959dh * If too many retries, mark phy dead and restart discovery;
145e0143b4896d03ce53b1af6787afa1a7e73959dh * otherwise schedule ds recovery.
145e0143b4896d03ce53b1af6787afa1a7e73959dh */
145e0143b4896d03ce53b1af6787afa1a7e73959dhstatic void
145e0143b4896d03ce53b1af6787afa1a7e73959dhpmcs_handle_ds_recovery_error(pmcs_phy_t *phyp, pmcs_xscsi_t *tgt,
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana pmcs_hw_t *pwp, const char *func_name, char *reason_string)
145e0143b4896d03ce53b1af6787afa1a7e73959dh{
145e0143b4896d03ce53b1af6787afa1a7e73959dh ASSERT(mutex_owned(&phyp->phy_lock));
145e0143b4896d03ce53b1af6787afa1a7e73959dh ASSERT((tgt == NULL) || mutex_owned(&tgt->statlock));
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh phyp->ds_recovery_retries++;
145e0143b4896d03ce53b1af6787afa1a7e73959dh
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (phyp->ds_recovery_retries > PMCS_MAX_DS_RECOVERY_RETRIES) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, tgt,
145e0143b4896d03ce53b1af6787afa1a7e73959dh "%s: retry limit reached after %s to PHY %s failed",
145e0143b4896d03ce53b1af6787afa1a7e73959dh func_name, reason_string, phyp->path);
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (tgt != NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh tgt->recover_wait = 0;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana /*
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana * Mark the PHY as dead and it and its parent as changed,
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana * then restart discovery
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana */
145e0143b4896d03ce53b1af6787afa1a7e73959dh phyp->dead = 1;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana PHY_CHANGED(pwp, phyp);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana if (phyp->parent)
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana PHY_CHANGED(pwp, phyp->parent);
145e0143b4896d03ce53b1af6787afa1a7e73959dh RESTART_DISCOVERY(pwp);
145e0143b4896d03ce53b1af6787afa1a7e73959dh } else if ((phyp->ds_prev_good_recoveries >
145e0143b4896d03ce53b1af6787afa1a7e73959dh PMCS_MAX_DS_RECOVERY_RETRIES) &&
145e0143b4896d03ce53b1af6787afa1a7e73959dh (phyp->last_good_recovery + drv_usectohz(PMCS_MAX_DS_RECOVERY_TIME)
145e0143b4896d03ce53b1af6787afa1a7e73959dh < ddi_get_lbolt())) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, tgt, "%s: max number of "
145e0143b4896d03ce53b1af6787afa1a7e73959dh "successful recoveries reached, declaring PHY %s dead",
145e0143b4896d03ce53b1af6787afa1a7e73959dh __func__, phyp->path);
145e0143b4896d03ce53b1af6787afa1a7e73959dh if (tgt != NULL) {
145e0143b4896d03ce53b1af6787afa1a7e73959dh tgt->recover_wait = 0;
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana /*
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana * Mark the PHY as dead and its parent as changed,
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana * then restart discovery
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana */
145e0143b4896d03ce53b1af6787afa1a7e73959dh phyp->dead = 1;
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana PHY_CHANGED(pwp, phyp);
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana if (phyp->parent)
601c90f161ff0319c1b4a2c3362b466043a65d8dSrikanth, Ramana PHY_CHANGED(pwp, phyp->parent);
145e0143b4896d03ce53b1af6787afa1a7e73959dh RESTART_DISCOVERY(pwp);
145e0143b4896d03ce53b1af6787afa1a7e73959dh } else {
145e0143b4896d03ce53b1af6787afa1a7e73959dh SCHEDULE_WORK(pwp, PMCS_WORK_DS_ERR_RECOVERY);
145e0143b4896d03ce53b1af6787afa1a7e73959dh }
145e0143b4896d03ce53b1af6787afa1a7e73959dh}