int asd_I_T_nexus_reset(struct domain_device *dev) { int res, tmp_res, i; struct sas_phy *phy = sas_find_local_phy(dev); /* Standard mandates link reset for ATA (type 0) and * hard reset for SSP (type 1) */ int reset_type = (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) ? 0 : 1; asd_clear_nexus_I_T(dev, NEXUS_PHASE_PRE); /* send a hard reset */ ASD_DPRINTK("sending %s reset to %s\n", reset_type ? "hard" : "soft", dev_name(&phy->dev)); res = sas_phy_reset(phy, reset_type); if (res == TMF_RESP_FUNC_COMPLETE) { /* wait for the maximum settle time */ msleep(500); /* clear all outstanding commands (keep nexus suspended) */ asd_clear_nexus_I_T(dev, NEXUS_PHASE_POST); } for (i = 0 ; i < 3; i++) { tmp_res = asd_clear_nexus_I_T(dev, NEXUS_PHASE_RESUME); if (tmp_res == TC_RESUME) return res; msleep(500); } /* This is a bit of a problem: the sequencer is still suspended * and is refusing to resume. Hope it will resume on a bigger hammer * or the disk is lost */ dev_printk(KERN_ERR, &phy->dev, "Failed to resume nexus after reset 0x%x\n", tmp_res); return TMF_RESP_FUNC_FAILED; }
int asd_I_T_nexus_reset(struct domain_device *dev) { int res, tmp_res, i; struct sas_phy *phy = sas_get_local_phy(dev); int reset_type = (dev->dev_type == SATA_DEV || (dev->tproto & SAS_PROTOCOL_STP)) ? 0 : 1; asd_clear_nexus_I_T(dev, NEXUS_PHASE_PRE); ASD_DPRINTK("sending %s reset to %s\n", reset_type ? "hard" : "soft", dev_name(&phy->dev)); res = sas_phy_reset(phy, reset_type); if (res == TMF_RESP_FUNC_COMPLETE || res == -ENODEV) { msleep(500); asd_clear_nexus_I_T(dev, NEXUS_PHASE_POST); } for (i = 0 ; i < 3; i++) { tmp_res = asd_clear_nexus_I_T(dev, NEXUS_PHASE_RESUME); if (tmp_res == TC_RESUME) goto out; msleep(500); } dev_printk(KERN_ERR, &phy->dev, "Failed to resume nexus after reset 0x%x\n", tmp_res); res = TMF_RESP_FUNC_FAILED; out: sas_put_local_phy(phy); return res; }
static int isci_reset_device(struct isci_host *ihost, struct domain_device *dev, struct isci_remote_device *idev) { int rc; unsigned long flags; enum sci_status status; struct sas_phy *phy = sas_get_local_phy(dev); struct isci_port *iport = dev->port->lldd_port; dev_dbg(&ihost->pdev->dev, "%s: idev %p\n", __func__, idev); spin_lock_irqsave(&ihost->scic_lock, flags); status = sci_remote_device_reset(idev); spin_unlock_irqrestore(&ihost->scic_lock, flags); if (status != SCI_SUCCESS) { dev_dbg(&ihost->pdev->dev, "%s: sci_remote_device_reset(%p) returned %d!\n", __func__, idev, status); rc = TMF_RESP_FUNC_FAILED; goto out; } if (scsi_is_sas_phy_local(phy)) { struct isci_phy *iphy = &ihost->phys[phy->number]; rc = isci_port_perform_hard_reset(ihost, iport, iphy); } else rc = sas_phy_reset(phy, !dev_is_sata(dev)); /* Terminate in-progress I/O now. */ isci_remote_device_nuke_requests(ihost, idev); /* Since all pending TCs have been cleaned, resume the RNC. */ spin_lock_irqsave(&ihost->scic_lock, flags); status = sci_remote_device_reset_complete(idev); spin_unlock_irqrestore(&ihost->scic_lock, flags); if (status != SCI_SUCCESS) { dev_dbg(&ihost->pdev->dev, "%s: sci_remote_device_reset_complete(%p) " "returned %d!\n", __func__, idev, status); } dev_dbg(&ihost->pdev->dev, "%s: idev %p complete.\n", __func__, idev); out: sas_put_local_phy(phy); return rc; }
static int isci_reset_device(struct isci_host *ihost, struct domain_device *dev, struct isci_remote_device *idev) { int rc = TMF_RESP_FUNC_COMPLETE, reset_stat = -1; struct sas_phy *phy = sas_get_local_phy(dev); struct isci_port *iport = dev->port->lldd_port; dev_dbg(&ihost->pdev->dev, "%s: idev %p\n", __func__, idev); /* Suspend the RNC, terminate all outstanding TCs. */ if (isci_remote_device_suspend_terminate(ihost, idev, NULL) != SCI_SUCCESS) { rc = TMF_RESP_FUNC_FAILED; goto out; } /* Note that since the termination for outstanding requests succeeded, * this function will return success. This is because the resets will * only fail if the device has been removed (ie. hotplug), and the * primary duty of this function is to cleanup tasks, so that is the * relevant status. */ if (!test_bit(IDEV_GONE, &idev->flags)) { if (scsi_is_sas_phy_local(phy)) { struct isci_phy *iphy = &ihost->phys[phy->number]; reset_stat = isci_port_perform_hard_reset(ihost, iport, iphy); } else reset_stat = sas_phy_reset(phy, !dev_is_sata(dev)); } /* Explicitly resume the RNC here, since there was no task sent. */ isci_remote_device_resume_from_abort(ihost, idev); dev_dbg(&ihost->pdev->dev, "%s: idev %p complete, reset_stat=%d.\n", __func__, idev, reset_stat); out: sas_put_local_phy(phy); return rc; }