From 1ca1e43e55f4cd068f997154ffaf5fa62b08b802 Mon Sep 17 00:00:00 2001
From: Dave Jiang <dave.jiang@intel.com>
Date: Tue, 24 May 2011 13:18:04 -0700
Subject: [SCSI] libsas: Add option for SATA soft reset

This allows a libsas driver to optionally provide a soft reset handler
for libata to drive.  The isci driver allows software to control the
assertion/deassertion of SRST.

[jejb: checkpatch.pl fixes]
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: James Bottomley <jbottomley@parallels.com>
---
 drivers/scsi/libsas/sas_ata.c | 40 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 39 insertions(+), 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index e99301421409..db9238f2ecb8 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -295,6 +295,44 @@ static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class,
 	return ret;
 }
 
+static int sas_ata_soft_reset(struct ata_link *link, unsigned int *class,
+			       unsigned long deadline)
+{
+	struct ata_port *ap = link->ap;
+	struct domain_device *dev = ap->private_data;
+	struct sas_internal *i =
+		to_sas_internal(dev->port->ha->core.shost->transportt);
+	int res = TMF_RESP_FUNC_FAILED;
+	int ret = 0;
+
+	if (i->dft->lldd_ata_soft_reset)
+		res = i->dft->lldd_ata_soft_reset(dev);
+
+	if (res != TMF_RESP_FUNC_COMPLETE) {
+		SAS_DPRINTK("%s: Unable to soft reset\n", __func__);
+		ret = -EAGAIN;
+	}
+
+	switch (dev->sata_dev.command_set) {
+	case ATA_COMMAND_SET:
+		SAS_DPRINTK("%s: Found ATA device.\n", __func__);
+		*class = ATA_DEV_ATA;
+		break;
+	case ATAPI_COMMAND_SET:
+		SAS_DPRINTK("%s: Found ATAPI device.\n", __func__);
+		*class = ATA_DEV_ATAPI;
+		break;
+	default:
+		SAS_DPRINTK("%s: Unknown SATA command set: %d.\n",
+			    __func__, dev->sata_dev.command_set);
+		*class = ATA_DEV_UNKNOWN;
+		break;
+	}
+
+	ap->cbl = ATA_CBL_SATA;
+	return ret;
+}
+
 static void sas_ata_post_internal(struct ata_queued_cmd *qc)
 {
 	if (qc->flags & ATA_QCFLAG_FAILED)
@@ -325,7 +363,7 @@ static void sas_ata_post_internal(struct ata_queued_cmd *qc)
 
 static struct ata_port_operations sas_sata_ops = {
 	.prereset		= ata_std_prereset,
-	.softreset		= NULL,
+	.softreset		= sas_ata_soft_reset,
 	.hardreset		= sas_ata_hard_reset,
 	.postreset		= ata_std_postreset,
 	.error_handler		= ata_std_error_handler,
-- 
cgit v1.2.3