From 0aa1113d544226bc2c4a20d6ac1d71170512a361 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 7 Apr 2008 22:47:18 +0900 Subject: [PATCH] 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 --- drivers/ata/libata-core.c | 17 ++++------------ drivers/ata/libata-sff.c | 43 +++++++++++++++++++++++++++++++++++++++ include/linux/libata.h | 1 + 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index fd912ccb90..5f771bb443 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -74,7 +74,7 @@ const unsigned long sata_deb_timing_hotplug[] = { 25, 500, 2000 }; const unsigned long sata_deb_timing_long[] = { 100, 2000, 5000 }; const struct ata_port_operations ata_base_port_ops = { - .prereset = ata_sff_prereset, + .prereset = ata_std_prereset, .hardreset = sata_sff_hardreset, .postreset = ata_sff_postreset, .error_handler = ata_std_error_handler, @@ -3416,7 +3416,7 @@ int sata_link_resume(struct ata_link *link, const unsigned long *params, } /** - * ata_sff_prereset - prepare for reset + * ata_std_prereset - prepare for reset * @link: ATA link to be reset * @deadline: deadline jiffies for the operation * @@ -3432,7 +3432,7 @@ int sata_link_resume(struct ata_link *link, const unsigned long *params, * RETURNS: * 0 on success, -errno otherwise. */ -int ata_sff_prereset(struct ata_link *link, unsigned long deadline) +int ata_std_prereset(struct ata_link *link, unsigned long deadline) { struct ata_port *ap = link->ap; struct ata_eh_context *ehc = &link->eh_context; @@ -3452,16 +3452,6 @@ int ata_sff_prereset(struct ata_link *link, unsigned long deadline) "link for reset (errno=%d)\n", rc); } - /* 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; } @@ -6104,6 +6094,7 @@ EXPORT_SYMBOL_GPL(ata_dev_disable); EXPORT_SYMBOL_GPL(sata_set_spd); 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(ata_dev_classify); EXPORT_SYMBOL_GPL(ata_dev_pair); diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index c116016171..9234bc0479 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, @@ -1606,6 +1607,48 @@ void ata_sff_thaw(struct ata_port *ap) ap->ops->sff_irq_on(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 diff --git a/include/linux/libata.h b/include/linux/libata.h index 603712b59c..595ede55fe 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -824,6 +824,7 @@ static inline int ata_port_is_dummy(struct ata_port *ap) extern void sata_print_link_status(struct ata_link *link); extern void ata_port_probe(struct ata_port *); extern int sata_set_spd(struct ata_link *link); +extern int ata_std_prereset(struct ata_link *link, unsigned long deadline); extern int sata_link_debounce(struct ata_link *link, const unsigned long *params, unsigned long deadline); extern int sata_link_resume(struct ata_link *link, const unsigned long *params, -- 2.39.5