aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-eh.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-02-02 02:22:30 -0500
committerJeff Garzik <jeff@garzik.org>2007-02-21 04:58:16 -0500
commit4ae72a1e469a3bcfd3c1f77dac62392c489bf9ca (patch)
tree8408499b85ddbe70077671117aa30da274f03363 /drivers/ata/libata-eh.c
parent458337dbb120d33f326e2b19d54eca8cf179b5c0 (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/ata/libata-eh.c')
-rw-r--r--drivers/ata/libata-eh.c35
1 files changed, 18 insertions, 17 deletions
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]) {