summaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-sff.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2008-04-07 22:47:18 +0900
committerJeff Garzik <jgarzik@redhat.com>2008-04-17 15:44:22 -0400
commit0aa1113d544226bc2c4a20d6ac1d71170512a361 (patch)
tree503b33b0805424d312abddd3535c941bb85c03bc /drivers/ata/libata-sff.c
parent288623a06c652239d2f57d271af12bb024cf7218 (diff)
downloadlinux-0aa1113d544226bc2c4a20d6ac1d71170512a361.tar.gz
linux-0aa1113d544226bc2c4a20d6ac1d71170512a361.tar.bz2
linux-0aa1113d544226bc2c4a20d6ac1d71170512a361.zip
libata: separate out ata_std_prereset() from ata_sff_prereset()
Separate out generic ATA portion from ata_sff_prereset() into ata_std_prereset() and implement ata_sff_prereset() using the std version. Waiting for device readiness is the only SFF specific part. ata_base_port_ops now has ata_std_prereset() for its prereset and ata_sff_port_ops overrides it to ata_sff_prereset(). This change can affect pdc_adma, ahci, sata_fsl and sata_sil24. pdc_adma implements its own prereset using ata_sff_prereset() and the rest has hardreset and thus are unaffected by this change. This change reflects real world situation. There is no generic way to wait for device readiness for non-SFF controllers and some of them don't have any mechanism for that. Non-sff drivers which don't have hardreset should wrap ata_std_prereset() and wait for device readiness itself but there's no such driver now and isn't likely to be popular in the future either. Signed-off-by: Tejun Heo <htejun@gmail.com>
Diffstat (limited to 'drivers/ata/libata-sff.c')
-rw-r--r--drivers/ata/libata-sff.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index c11601617134..9234bc047956 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -47,6 +47,7 @@ const struct ata_port_operations ata_sff_port_ops = {
.freeze = ata_sff_freeze,
.thaw = ata_sff_thaw,
+ .prereset = ata_sff_prereset,
.softreset = ata_sff_softreset,
.error_handler = ata_sff_error_handler,
.post_internal_cmd = ata_sff_post_internal_cmd,
@@ -1607,6 +1608,48 @@ void ata_sff_thaw(struct ata_port *ap)
}
/**
+ * ata_sff_prereset - prepare SFF link for reset
+ * @link: SFF link to be reset
+ * @deadline: deadline jiffies for the operation
+ *
+ * SFF link @link is about to be reset. Initialize it. It first
+ * calls ata_std_prereset() and wait for !BSY if the port is
+ * being softreset.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep)
+ *
+ * RETURNS:
+ * 0 on success, -errno otherwise.
+ */
+int ata_sff_prereset(struct ata_link *link, unsigned long deadline)
+{
+ struct ata_port *ap = link->ap;
+ struct ata_eh_context *ehc = &link->eh_context;
+ int rc;
+
+ rc = ata_std_prereset(link, deadline);
+ if (rc)
+ return rc;
+
+ /* if we're about to do hardreset, nothing more to do */
+ if (ehc->i.action & ATA_EH_HARDRESET)
+ return 0;
+
+ /* wait for !BSY if we don't know that no device is attached */
+ if (!ata_link_offline(link)) {
+ rc = ata_sff_wait_ready(ap, deadline);
+ if (rc && rc != -ENODEV) {
+ ata_link_printk(link, KERN_WARNING, "device not ready "
+ "(errno=%d), forcing hardreset\n", rc);
+ ehc->i.action |= ATA_EH_HARDRESET;
+ }
+ }
+
+ return 0;
+}
+
+/**
* ata_devchk - PATA device presence detection
* @ap: ATA channel to examine
* @device: Device to examine (starting at zero)