diff options
author | Tejun Heo <htejun@gmail.com> | 2008-01-23 18:05:14 +0300 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2008-04-17 23:44:15 +0400 |
commit | cf48062658e7ab3bc55e10c65676c3c73c16f8bf (patch) | |
tree | 9a50a016ceb6051d8a30a43ea39f2a4d3d25570e /drivers/ata/libata-pmp.c | |
parent | 4b119e21d0c66c22e8ca03df05d9de623d0eb50f (diff) | |
download | linux-cf48062658e7ab3bc55e10c65676c3c73c16f8bf.tar.xz |
libata: prefer hardreset
When both soft and hard resets are available, libata preferred
softreset till now. The logic behind it was to be softer to devices;
however, this doesn't really help much. Rationales for the change:
* BIOS may freeze lock certain things during boot and softreset can't
unlock those. This by itself is okay but during operation PHY event
or other error conditions can trigger hardreset and the device may
end up with different configuration.
For example, after a hardreset, previously unlockable HPA can be
unlocked resulting in different device size and thus revalidation
failure. Similar condition can occur during or after resume.
* Certain ATAPI devices require hardreset to recover after certain
error conditions. On PATA, this is done by issuing the DEVICE RESET
command. On SATA, COMRESET has equivalent effect. The problem is
that DEVICE RESET needs its own execution protocol.
For SFF controllers with bare TF access, it can be easily
implemented but more advanced controllers (e.g. ahci and sata_sil24)
require specialized implementations. Simply using hardreset solves
the problem nicely.
* COMRESET initialization sequence is the norm in SATA land and many
SATA devices don't work properly if only SRST is used. For example,
some PMPs behave this way and libata works around by always issuing
hardreset if the host supports PMP.
Like the above example, libata has developed a number of mechanisms
aiming to promote softreset to hardreset if softreset is not going
to work. This approach is time consuming and error prone.
Also, note that, dependingon how you read the specs, it could be
argued that PMP fan-out ports require COMRESET to start operation.
In fact, all the PMPs on the market except one don't work properly
if COMRESET is not issued to fan-out ports after PMP reset.
* COMRESET is an integral part of SATA connection and any working
device should be able to handle COMRESET properly. After all, it's
the way to signal hardreset during reboot. This is the most used
and recommended (at least by the ahci spec) method of resetting
devices.
So, this patch makes libata prefer hardreset over softreset by making
the following changes.
* Rename ATA_EH_RESET_MASK to ATA_EH_RESET and use it whereever
ATA_EH_{SOFT|HARD}RESET used to be used. ATA_EH_{SOFT|HARD}RESET is
now only used to tell prereset whether soft or hard reset will be
issued.
* Strip out now unneeded promote-to-hardreset logics from
ata_eh_reset(), ata_std_prereset(), sata_pmp_std_prereset() and
other places.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Diffstat (limited to 'drivers/ata/libata-pmp.c')
-rw-r--r-- | drivers/ata/libata-pmp.c | 28 |
1 files changed, 8 insertions, 20 deletions
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index d91f5090ba9d..8439fc8efdd6 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -194,15 +194,6 @@ int sata_pmp_std_prereset(struct ata_link *link, unsigned long deadline) const unsigned long *timing = sata_ehc_deb_timing(ehc); int rc; - /* force HRST? */ - if (link->flags & ATA_LFLAG_NO_SRST) - ehc->i.action |= ATA_EH_HARDRESET; - - /* handle link resume */ - if ((ehc->i.flags & ATA_EHI_RESUME_LINK) && - (link->flags & ATA_LFLAG_HRST_TO_RESUME)) - ehc->i.action |= ATA_EH_HARDRESET; - /* if we're about to do hardreset, nothing more to do */ if (ehc->i.action & ATA_EH_HARDRESET) return 0; @@ -445,7 +436,7 @@ static int sata_pmp_init_links(struct ata_port *ap, int nr_ports) link->flags = 0; ehc->i.probe_mask |= 1; - ehc->i.action |= ATA_EH_SOFTRESET; + ehc->i.action |= ATA_EH_RESET; ehc->i.flags |= ATA_EHI_RESUME_LINK; } @@ -840,13 +831,12 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap, retry: ehc->classes[0] = ATA_DEV_UNKNOWN; - if (ehc->i.action & ATA_EH_RESET_MASK) { + if (ehc->i.action & ATA_EH_RESET) { struct ata_link *tlink; ata_eh_freeze_port(ap); /* reset */ - ehc->i.action = ATA_EH_HARDRESET; rc = ata_eh_reset(link, 0, prereset, softreset, hardreset, postreset); if (rc) { @@ -890,11 +880,11 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap, reval_failed = 1; ata_dev_printk(dev, KERN_WARNING, - "retrying hardreset%s\n", + "retrying reset%s\n", sleep ? " in 5 secs" : ""); if (sleep) ssleep(5); - ehc->i.action |= ATA_EH_HARDRESET; + ehc->i.action |= ATA_EH_RESET; goto retry; } else { ata_dev_printk(dev, KERN_ERR, "failed to recover PMP " @@ -938,10 +928,8 @@ static int sata_pmp_eh_handle_disabled_links(struct ata_port *ap) /* Some PMPs require hardreset sequence to get * SError.N working. */ - if ((link->flags & ATA_LFLAG_HRST_TO_RESUME) && - (link->eh_context.i.flags & ATA_EHI_RESUME_LINK)) - sata_link_hardreset(link, sata_deb_timing_normal, - jiffies + ATA_TMOUT_INTERNAL_QUICK); + sata_link_hardreset(link, sata_deb_timing_normal, + jiffies + ATA_TMOUT_INTERNAL_QUICK); /* unconditionally clear SError.N */ rc = sata_scr_write(link, SCR_ERROR, SERR_PHYRDY_CHG); @@ -1124,7 +1112,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap, link_fail: if (sata_pmp_handle_link_fail(link, link_tries)) { - pmp_ehc->i.action |= ATA_EH_HARDRESET; + pmp_ehc->i.action |= ATA_EH_RESET; goto retry; } @@ -1142,7 +1130,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap, if (--pmp_tries) { ata_port_printk(ap, KERN_WARNING, "failed to recover PMP, retrying in 5 secs\n"); - pmp_ehc->i.action |= ATA_EH_HARDRESET; + pmp_ehc->i.action |= ATA_EH_RESET; ssleep(5); goto retry; } |