Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}