diff options
author | Tejun Heo <htejun@gmail.com> | 2007-02-02 02:22:30 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-02-21 04:58:16 -0500 |
commit | 4ae72a1e469a3bcfd3c1f77dac62392c489bf9ca (patch) | |
tree | 8408499b85ddbe70077671117aa30da274f03363 /drivers | |
parent | 458337dbb120d33f326e2b19d54eca8cf179b5c0 (diff) |
libata: improve probe failure handling
* Move forcing device to PIO0 on device disable into
ata_dev_disable(). This makes both old and new EHs act the same
way.
* Speed down only PIO mode on probe failure. All commands used during
probing are PIO commands. There's no point in speeding down DMA.
* Retry at least once after -ENODEV. Some devices report garbled
IDENTIFY data after certain events. This shouldn't cause device
detach and re-attach.
* Rearrange EH failure path for simplicity.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ata/libata-core.c | 39 | ||||
-rw-r--r-- | drivers/ata/libata-eh.c | 35 |
2 files changed, 37 insertions, 37 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 249d487c091e..24c6505f062d 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -600,6 +600,8 @@ void ata_dev_disable(struct ata_device *dev) | |||
600 | { | 600 | { |
601 | if (ata_dev_enabled(dev) && ata_msg_drv(dev->ap)) { | 601 | if (ata_dev_enabled(dev) && ata_msg_drv(dev->ap)) { |
602 | ata_dev_printk(dev, KERN_WARNING, "disabled\n"); | 602 | ata_dev_printk(dev, KERN_WARNING, "disabled\n"); |
603 | ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0 | | ||
604 | ATA_DNXFER_QUIET); | ||
603 | dev->class++; | 605 | dev->class++; |
604 | } | 606 | } |
605 | } | 607 | } |
@@ -1778,9 +1780,8 @@ int ata_bus_probe(struct ata_port *ap) | |||
1778 | { | 1780 | { |
1779 | unsigned int classes[ATA_MAX_DEVICES]; | 1781 | unsigned int classes[ATA_MAX_DEVICES]; |
1780 | int tries[ATA_MAX_DEVICES]; | 1782 | int tries[ATA_MAX_DEVICES]; |
1781 | int i, rc, down_xfermask; | 1783 | int i, rc; |
1782 | struct ata_device *dev; | 1784 | struct ata_device *dev; |
1783 | int dnxfer_sel; | ||
1784 | 1785 | ||
1785 | ata_port_probe(ap); | 1786 | ata_port_probe(ap); |
1786 | 1787 | ||
@@ -1788,8 +1789,6 @@ int ata_bus_probe(struct ata_port *ap) | |||
1788 | tries[i] = ATA_PROBE_MAX_TRIES; | 1789 | tries[i] = ATA_PROBE_MAX_TRIES; |
1789 | 1790 | ||
1790 | retry: | 1791 | retry: |
1791 | down_xfermask = 0; | ||
1792 | |||
1793 | /* reset and determine device classes */ | 1792 | /* reset and determine device classes */ |
1794 | ap->ops->phy_reset(ap); | 1793 | ap->ops->phy_reset(ap); |
1795 | 1794 | ||
@@ -1837,10 +1836,8 @@ int ata_bus_probe(struct ata_port *ap) | |||
1837 | 1836 | ||
1838 | /* configure transfer mode */ | 1837 | /* configure transfer mode */ |
1839 | rc = ata_set_mode(ap, &dev); | 1838 | rc = ata_set_mode(ap, &dev); |
1840 | if (rc) { | 1839 | if (rc) |
1841 | down_xfermask = 1; | ||
1842 | goto fail; | 1840 | goto fail; |
1843 | } | ||
1844 | 1841 | ||
1845 | for (i = 0; i < ATA_MAX_DEVICES; i++) | 1842 | for (i = 0; i < ATA_MAX_DEVICES; i++) |
1846 | if (ata_dev_enabled(&ap->device[i])) | 1843 | if (ata_dev_enabled(&ap->device[i])) |
@@ -1852,27 +1849,29 @@ int ata_bus_probe(struct ata_port *ap) | |||
1852 | return -ENODEV; | 1849 | return -ENODEV; |
1853 | 1850 | ||
1854 | fail: | 1851 | fail: |
1852 | tries[dev->devno]--; | ||
1853 | |||
1855 | switch (rc) { | 1854 | switch (rc) { |
1856 | case -EINVAL: | 1855 | case -EINVAL: |
1857 | case -ENODEV: | 1856 | /* eeek, something went very wrong, give up */ |
1858 | tries[dev->devno] = 0; | 1857 | tries[dev->devno] = 0; |
1859 | break; | 1858 | break; |
1859 | |||
1860 | case -ENODEV: | ||
1861 | /* give it just one more chance */ | ||
1862 | tries[dev->devno] = min(tries[dev->devno], 1); | ||
1860 | case -EIO: | 1863 | case -EIO: |
1861 | sata_down_spd_limit(ap); | 1864 | if (tries[dev->devno] == 1) { |
1862 | /* fall through */ | 1865 | /* This is the last chance, better to slow |
1863 | default: | 1866 | * down than lose it. |
1864 | tries[dev->devno]--; | 1867 | */ |
1865 | dnxfer_sel = ATA_DNXFER_ANY; | 1868 | sata_down_spd_limit(ap); |
1866 | if (tries[dev->devno] == 1) | 1869 | ata_down_xfermask_limit(dev, ATA_DNXFER_PIO); |
1867 | dnxfer_sel = ATA_DNXFER_FORCE_PIO0; | 1870 | } |
1868 | if (down_xfermask && ata_down_xfermask_limit(dev, dnxfer_sel)) | ||
1869 | tries[dev->devno] = 0; | ||
1870 | } | 1871 | } |
1871 | 1872 | ||
1872 | if (!tries[dev->devno]) { | 1873 | if (!tries[dev->devno]) |
1873 | ata_down_xfermask_limit(dev, ATA_DNXFER_FORCE_PIO0); | ||
1874 | ata_dev_disable(dev); | 1874 | ata_dev_disable(dev); |
1875 | } | ||
1876 | 1875 | ||
1877 | goto retry; | 1876 | goto retry; |
1878 | } | 1877 | } |
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 7b61562cdd40..1abfdba8d99b 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
@@ -1964,8 +1964,7 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
1964 | { | 1964 | { |
1965 | struct ata_eh_context *ehc = &ap->eh_context; | 1965 | struct ata_eh_context *ehc = &ap->eh_context; |
1966 | struct ata_device *dev; | 1966 | struct ata_device *dev; |
1967 | int down_xfermask, i, rc; | 1967 | int i, rc; |
1968 | int dnxfer_sel; | ||
1969 | 1968 | ||
1970 | DPRINTK("ENTER\n"); | 1969 | DPRINTK("ENTER\n"); |
1971 | 1970 | ||
@@ -1994,7 +1993,6 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
1994 | } | 1993 | } |
1995 | 1994 | ||
1996 | retry: | 1995 | retry: |
1997 | down_xfermask = 0; | ||
1998 | rc = 0; | 1996 | rc = 0; |
1999 | 1997 | ||
2000 | /* if UNLOADING, finish immediately */ | 1998 | /* if UNLOADING, finish immediately */ |
@@ -2039,10 +2037,8 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
2039 | /* configure transfer mode if necessary */ | 2037 | /* configure transfer mode if necessary */ |
2040 | if (ehc->i.flags & ATA_EHI_SETMODE) { | 2038 | if (ehc->i.flags & ATA_EHI_SETMODE) { |
2041 | rc = ata_set_mode(ap, &dev); | 2039 | rc = ata_set_mode(ap, &dev); |
2042 | if (rc) { | 2040 | if (rc) |
2043 | down_xfermask = 1; | ||
2044 | goto dev_fail; | 2041 | goto dev_fail; |
2045 | } | ||
2046 | ehc->i.flags &= ~ATA_EHI_SETMODE; | 2042 | ehc->i.flags &= ~ATA_EHI_SETMODE; |
2047 | } | 2043 | } |
2048 | 2044 | ||
@@ -2054,22 +2050,27 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, | |||
2054 | goto out; | 2050 | goto out; |
2055 | 2051 | ||
2056 | dev_fail: | 2052 | dev_fail: |
2053 | ehc->tries[dev->devno]--; | ||
2054 | |||
2057 | switch (rc) { | 2055 | switch (rc) { |
2058 | case -ENODEV: | ||
2059 | /* device missing, schedule probing */ | ||
2060 | ehc->i.probe_mask |= (1 << dev->devno); | ||
2061 | case -EINVAL: | 2056 | case -EINVAL: |
2057 | /* eeek, something went very wrong, give up */ | ||
2062 | ehc->tries[dev->devno] = 0; | 2058 | ehc->tries[dev->devno] = 0; |
2063 | break; | 2059 | break; |
2060 | |||
2061 | case -ENODEV: | ||
2062 | /* device missing or wrong IDENTIFY data, schedule probing */ | ||
2063 | ehc->i.probe_mask |= (1 << dev->devno); | ||
2064 | /* give it just one more chance */ | ||
2065 | ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1); | ||
2064 | case -EIO: | 2066 | case -EIO: |
2065 | sata_down_spd_limit(ap); | 2067 | if (ehc->tries[dev->devno] == 1) { |
2066 | default: | 2068 | /* This is the last chance, better to slow |
2067 | ehc->tries[dev->devno]--; | 2069 | * down than lose it. |
2068 | dnxfer_sel = ATA_DNXFER_ANY; | 2070 | */ |
2069 | if (ehc->tries[dev->devno] == 1) | 2071 | sata_down_spd_limit(ap); |
2070 | dnxfer_sel = ATA_DNXFER_FORCE_PIO0; | 2072 | ata_down_xfermask_limit(dev, ATA_DNXFER_PIO); |
2071 | if (down_xfermask && ata_down_xfermask_limit(dev, dnxfer_sel)) | 2073 | } |
2072 | ehc->tries[dev->devno] = 0; | ||
2073 | } | 2074 | } |
2074 | 2075 | ||
2075 | if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) { | 2076 | if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) { |