libata: implement and use sata_std_hardreset()
Tejun Heo [Mon, 7 Apr 2008 13:47:19 +0000 (22:47 +0900)]
Implement sata_std_hardreset(), which simply wraps around
sata_link_hardreset().  sata_std_hardreset() becomes new standard
hardreset method for sata_port_ops and sata_sff_hardreset() moves from
ata_base_port_ops to ata_sff_port_ops, which is where it really
belongs.

ata_is_builtin_hardreset() is added so that both
ata_std_error_handler() and ata_sff_error_handler() skip both builtin
hardresets if SCR isn't accessible.

piix_sidpr_hardreset() in ata_piix.c is identical to
sata_std_hardreset() in functionality and got replaced with the
standard function.

Signed-off-by: Tejun Heo <htejun@gmail.com>

drivers/ata/ata_piix.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/libata-sff.c
drivers/ata/libata.h
include/linux/libata.h

index f59a55b..b7c38ee 100644 (file)
@@ -165,8 +165,6 @@ static void piix_set_dmamode(struct ata_port *ap, struct ata_device *adev);
 static void ich_set_dmamode(struct ata_port *ap, struct ata_device *adev);
 static int ich_pata_cable_detect(struct ata_port *ap);
 static u8 piix_vmw_bmdma_status(struct ata_port *ap);
-static int piix_sidpr_hardreset(struct ata_link *link, unsigned int *class,
-                               unsigned long deadline);
 static int piix_sidpr_scr_read(struct ata_port *ap, unsigned int reg, u32 *val);
 static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val);
 #ifdef CONFIG_PM
@@ -319,7 +317,7 @@ static struct ata_port_operations piix_sata_ops = {
 
 static struct ata_port_operations piix_sidpr_sata_ops = {
        .inherits               = &piix_sata_ops,
-       .hardreset              = piix_sidpr_hardreset,
+       .hardreset              = sata_std_hardreset,
        .scr_read               = piix_sidpr_scr_read,
        .scr_write              = piix_sidpr_scr_write,
 };
@@ -1015,29 +1013,6 @@ static int piix_sidpr_scr_write(struct ata_port *ap, unsigned int reg, u32 val)
        return 0;
 }
 
-static int piix_sidpr_hardreset(struct ata_link *link, unsigned int *class,
-                               unsigned long deadline)
-{
-       const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
-       int rc;
-
-       /* do hardreset */
-       rc = sata_link_hardreset(link, timing, deadline, NULL, NULL);
-       if (rc) {
-               ata_link_printk(link, KERN_ERR,
-                               "COMRESET failed (errno=%d)\n", rc);
-               return rc;
-       }
-
-       /* TODO: phy layer with polling, timeouts, etc. */
-       if (ata_link_offline(link)) {
-               *class = ATA_DEV_NONE;
-               return 0;
-       }
-
-       return -EAGAIN;
-}
-
 #ifdef CONFIG_PM
 static int piix_broken_suspend(void)
 {
index b607292..c4fd4af 100644 (file)
@@ -75,7 +75,6 @@ const unsigned long sata_deb_timing_long[]            = { 100, 2000, 5000 };
 
 const struct ata_port_operations ata_base_port_ops = {
        .prereset               = ata_std_prereset,
-       .hardreset              = sata_sff_hardreset,
        .postreset              = ata_std_postreset,
        .error_handler          = ata_std_error_handler,
 };
@@ -84,6 +83,7 @@ const struct ata_port_operations sata_port_ops = {
        .inherits               = &ata_base_port_ops,
 
        .qc_defer               = ata_std_qc_defer,
+       .hardreset              = sata_std_hardreset,
        .sff_dev_select         = ata_noop_dev_select,
 };
 
@@ -3661,6 +3661,33 @@ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing,
 }
 
 /**
+ *     sata_std_hardreset - COMRESET w/o waiting or classification
+ *     @link: link to reset
+ *     @class: resulting class of attached device
+ *     @deadline: deadline jiffies for the operation
+ *
+ *     Standard SATA COMRESET w/o waiting or classification.
+ *
+ *     LOCKING:
+ *     Kernel thread context (may sleep)
+ *
+ *     RETURNS:
+ *     0 if link offline, -EAGAIN if link online, -errno on errors.
+ */
+int sata_std_hardreset(struct ata_link *link, unsigned int *class,
+                      unsigned long deadline)
+{
+       const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
+       bool online;
+       int rc;
+
+       /* do hardreset */
+       rc = sata_link_hardreset(link, timing, deadline, &online, NULL);
+       *class = ATA_DEV_NONE;
+       return online ? -EAGAIN : rc;
+}
+
+/**
  *     ata_std_postreset - standard postreset callback
  *     @link: the target ata_link
  *     @classes: classes of attached devices
@@ -6225,6 +6252,7 @@ EXPORT_SYMBOL_GPL(sata_link_debounce);
 EXPORT_SYMBOL_GPL(sata_link_resume);
 EXPORT_SYMBOL_GPL(ata_std_prereset);
 EXPORT_SYMBOL_GPL(sata_link_hardreset);
+EXPORT_SYMBOL_GPL(sata_std_hardreset);
 EXPORT_SYMBOL_GPL(ata_std_postreset);
 EXPORT_SYMBOL_GPL(ata_dev_classify);
 EXPORT_SYMBOL_GPL(ata_dev_pair);
index f4f9c27..21687bb 100644 (file)
@@ -2857,11 +2857,8 @@ void ata_std_error_handler(struct ata_port *ap)
        struct ata_port_operations *ops = ap->ops;
        ata_reset_fn_t hardreset = ops->hardreset;
 
-       /* sata_std_hardreset is inherited to all drivers from
-        * ata_base_port_ops.  Ignore it if SCR access is not
-        * available.
-        */
-       if (hardreset == sata_sff_hardreset && !sata_scr_valid(&ap->link))
+       /* ignore built-in hardreset if SCR access is not available */
+       if (ata_is_builtin_hardreset(hardreset) && !sata_scr_valid(&ap->link))
                hardreset = NULL;
 
        ata_do_eh(ap, ops->prereset, ops->softreset, hardreset, ops->postreset);
index 0b97e84..f464ca1 100644 (file)
@@ -49,6 +49,7 @@ const struct ata_port_operations ata_sff_port_ops = {
        .thaw                   = ata_sff_thaw,
        .prereset               = ata_sff_prereset,
        .softreset              = ata_sff_softreset,
+       .hardreset              = sata_sff_hardreset,
        .postreset              = ata_sff_postreset,
        .error_handler          = ata_sff_error_handler,
        .post_internal_cmd      = ata_sff_post_internal_cmd,
@@ -2031,14 +2032,12 @@ void ata_sff_error_handler(struct ata_port *ap)
 
        /* PIO and DMA engines have been stopped, perform recovery */
 
-       /* ata_sff_softreset and sata_sff_hardreset are inherited to
-        * all SFF drivers from ata_sff_port_ops.  Ignore softreset if
-        * ctl isn't accessible.  Ignore hardreset if SCR access isn't
-        * available.
+       /* Ignore ata_sff_softreset if ctl isn't accessible and
+        * built-in hardresets if SCR access isn't available.
         */
        if (softreset == ata_sff_softreset && !ap->ioaddr.ctl_addr)
                softreset = NULL;
-       if (hardreset == sata_sff_hardreset && !sata_scr_valid(&ap->link))
+       if (ata_is_builtin_hardreset(hardreset) && !sata_scr_valid(&ap->link))
                hardreset = NULL;
 
        ata_do_eh(ap, ap->ops->prereset, softreset, hardreset,
index 08af43e..87f54a1 100644 (file)
@@ -38,6 +38,15 @@ struct ata_scsi_args {
        void                    (*done)(struct scsi_cmnd *);
 };
 
+static inline int ata_is_builtin_hardreset(ata_reset_fn_t reset)
+{
+       if (reset == sata_std_hardreset)
+               return 1;
+       if (reset == sata_sff_hardreset)
+               return 1;
+       return 0;
+}
+
 /* libata-core.c */
 enum {
        /* flags for ata_dev_read_id() */
index d9ebce2..c060cd3 100644 (file)
@@ -853,6 +853,8 @@ extern int sata_link_resume(struct ata_link *link, const unsigned long *params,
 extern int sata_link_hardreset(struct ata_link *link,
                        const unsigned long *timing, unsigned long deadline,
                        bool *online, int (*check_ready)(struct ata_link *));
+extern int sata_std_hardreset(struct ata_link *link, unsigned int *class,
+                             unsigned long deadline);
 extern void ata_std_postreset(struct ata_link *link, unsigned int *classes);
 extern void ata_port_disable(struct ata_port *);