diff options
author | Tejun Heo <htejun@gmail.com> | 2007-07-01 06:05:58 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-07-10 21:46:03 -0400 |
commit | fee7ca72d3dae1078031b6fd272b9930f43bd3d1 (patch) | |
tree | 9746c1663527ecb9602c227355d32762cc0798d7 | |
parent | 790956e7bbf0a7b73e72b04d3bd63d974c7e29bb (diff) |
libata-link: separate out ata_eh_handle_dev_fail()
Separate out ata_eh_handle_dev_fail() from ata_eh_recover(). This is
in preparation of ata_link and PMP support.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r-- | drivers/ata/libata-eh.c | 96 |
1 files changed, 52 insertions, 44 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 9ee0a8c08d96..9aa62a0754f6 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
@@ -1897,6 +1897,57 @@ static int ata_eh_skip_recovery(struct ata_port *ap) | |||
1897 | return 1; | 1897 | return 1; |
1898 | } | 1898 | } |
1899 | 1899 | ||
1900 | static void ata_eh_handle_dev_fail(struct ata_device *dev, int err) | ||
1901 | { | ||
1902 | struct ata_port *ap = dev->ap; | ||
1903 | struct ata_eh_context *ehc = &ap->eh_context; | ||
1904 | |||
1905 | ehc->tries[dev->devno]--; | ||
1906 | |||
1907 | switch (err) { | ||
1908 | case -ENODEV: | ||
1909 | /* device missing or wrong IDENTIFY data, schedule probing */ | ||
1910 | ehc->i.probe_mask |= (1 << dev->devno); | ||
1911 | case -EINVAL: | ||
1912 | /* give it just one more chance */ | ||
1913 | ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1); | ||
1914 | case -EIO: | ||
1915 | if (ehc->tries[dev->devno] == 1) { | ||
1916 | /* This is the last chance, better to slow | ||
1917 | * down than lose it. | ||
1918 | */ | ||
1919 | sata_down_spd_limit(ap); | ||
1920 | ata_down_xfermask_limit(dev, ATA_DNXFER_PIO); | ||
1921 | } | ||
1922 | } | ||
1923 | |||
1924 | if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) { | ||
1925 | /* disable device if it has used up all its chances */ | ||
1926 | ata_dev_disable(dev); | ||
1927 | |||
1928 | /* detach if offline */ | ||
1929 | if (ata_port_offline(ap)) | ||
1930 | ata_eh_detach_dev(dev); | ||
1931 | |||
1932 | /* probe if requested */ | ||
1933 | if ((ehc->i.probe_mask & (1 << dev->devno)) && | ||
1934 | !(ehc->did_probe_mask & (1 << dev->devno))) { | ||
1935 | ata_eh_detach_dev(dev); | ||
1936 | ata_dev_init(dev); | ||
1937 | |||
1938 | ehc->tries[dev->devno] = ATA_EH_DEV_TRIES; | ||
1939 | ehc->did_probe_mask |= (1 << dev->devno); | ||
1940 | ehc->i.action |= ATA_EH_SOFTRESET; | ||
1941 | } | ||
1942 | } else { | ||
1943 | /* soft didn't work? be haaaaard */ | ||
1944 | if (ehc->i.flags & ATA_EHI_DID_RESET) | ||
1945 | ehc->i.action |= ATA_EH_HARDRESET; | ||
1946 | else | ||
1947 | ehc->i.action |= ATA_EH_SOFTRESET; | ||
1948 | } | ||
1949 | } | ||
1950 | |||
1900 | /** | 1951 | /** |
1901 | * ata_eh_recover - recover host port after error | 1952 | * ata_eh_recover - recover host port after error |
1902 | * @ap: host port to recover | 1953 | * @ap: host port to recover |
@@ -1997,50 +2048,7 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
1997 | goto out; | 2048 | goto out; |
1998 | 2049 | ||
1999 | dev_fail: | 2050 | dev_fail: |
2000 | ehc->tries[dev->devno]--; | 2051 | ata_eh_handle_dev_fail(dev, rc); |
2001 | |||
2002 | switch (rc) { | ||
2003 | case -ENODEV: | ||
2004 | /* device missing or wrong IDENTIFY data, schedule probing */ | ||
2005 | ehc->i.probe_mask |= (1 << dev->devno); | ||
2006 | case -EINVAL: | ||
2007 | /* give it just one more chance */ | ||
2008 | ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1); | ||
2009 | case -EIO: | ||
2010 | if (ehc->tries[dev->devno] == 1) { | ||
2011 | /* This is the last chance, better to slow | ||
2012 | * down than lose it. | ||
2013 | */ | ||
2014 | sata_down_spd_limit(ap); | ||
2015 | ata_down_xfermask_limit(dev, ATA_DNXFER_PIO); | ||
2016 | } | ||
2017 | } | ||
2018 | |||
2019 | if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) { | ||
2020 | /* disable device if it has used up all its chances */ | ||
2021 | ata_dev_disable(dev); | ||
2022 | |||
2023 | /* detach if offline */ | ||
2024 | if (ata_port_offline(ap)) | ||
2025 | ata_eh_detach_dev(dev); | ||
2026 | |||
2027 | /* probe if requested */ | ||
2028 | if ((ehc->i.probe_mask & (1 << dev->devno)) && | ||
2029 | !(ehc->did_probe_mask & (1 << dev->devno))) { | ||
2030 | ata_eh_detach_dev(dev); | ||
2031 | ata_dev_init(dev); | ||
2032 | |||
2033 | ehc->tries[dev->devno] = ATA_EH_DEV_TRIES; | ||
2034 | ehc->did_probe_mask |= (1 << dev->devno); | ||
2035 | ehc->i.action |= ATA_EH_SOFTRESET; | ||
2036 | } | ||
2037 | } else { | ||
2038 | /* soft didn't work? be haaaaard */ | ||
2039 | if (ehc->i.flags & ATA_EHI_DID_RESET) | ||
2040 | ehc->i.action |= ATA_EH_HARDRESET; | ||
2041 | else | ||
2042 | ehc->i.action |= ATA_EH_SOFTRESET; | ||
2043 | } | ||
2044 | 2052 | ||
2045 | if (ata_port_nr_enabled(ap)) { | 2053 | if (ata_port_nr_enabled(ap)) { |
2046 | ata_port_printk(ap, KERN_WARNING, "failed to recover some " | 2054 | ata_port_printk(ap, KERN_WARNING, "failed to recover some " |