[SCSI] libsas: Add option for SATA soft reset
authorDave Jiang <dave.jiang@intel.com>
Tue, 24 May 2011 20:18:04 +0000 (13:18 -0700)
committerJames Bottomley <jbottomley@parallels.com>
Fri, 27 May 2011 03:49:33 +0000 (22:49 -0500)
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
include/scsi/libsas.h

index e99301421409ad52e3d8e7cc5ecc52be48d7d076..db9238f2ecb8b7596dda9c2d4132000af0910bd7 100644 (file)
@@ -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,
index 8f6bb9c7f3eb1b038a784e4d706098f3442937ba..ee866060f8a4d2c6441cba43d6c27a454bacf1ed 100644 (file)
@@ -604,6 +604,7 @@ struct sas_domain_function_template {
        int (*lldd_clear_aca)(struct domain_device *, u8 *lun);
        int (*lldd_clear_task_set)(struct domain_device *, u8 *lun);
        int (*lldd_I_T_nexus_reset)(struct domain_device *);
+       int (*lldd_ata_soft_reset)(struct domain_device *);
        int (*lldd_lu_reset)(struct domain_device *, u8 *lun);
        int (*lldd_query_task)(struct sas_task *);