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/ata/libata-eh.c | |
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/ata/libata-eh.c')
-rw-r--r-- | drivers/ata/libata-eh.c | 35 |
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]) { |