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>
This commit is contained in:
Tejun Heo
2007-02-02 16:22:30 +09:00
committed by Jeff Garzik
parent 458337dbb1
commit 4ae72a1e46
2 changed files with 37 additions and 37 deletions

View File

@@ -1964,8 +1964,7 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
{
struct ata_eh_context *ehc = &ap->eh_context;
struct ata_device *dev;
int down_xfermask, i, rc;
int dnxfer_sel;
int i, rc;
DPRINTK("ENTER\n");
@@ -1994,7 +1993,6 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
}
retry:
down_xfermask = 0;
rc = 0;
/* if UNLOADING, finish immediately */
@@ -2039,10 +2037,8 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
/* configure transfer mode if necessary */
if (ehc->i.flags & ATA_EHI_SETMODE) {
rc = ata_set_mode(ap, &dev);
if (rc) {
down_xfermask = 1;
if (rc)
goto dev_fail;
}
ehc->i.flags &= ~ATA_EHI_SETMODE;
}
@@ -2054,22 +2050,27 @@ static int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
goto out;
dev_fail:
ehc->tries[dev->devno]--;
switch (rc) {
case -ENODEV:
/* device missing, schedule probing */
ehc->i.probe_mask |= (1 << dev->devno);
case -EINVAL:
/* eeek, something went very wrong, give up */
ehc->tries[dev->devno] = 0;
break;
case -ENODEV:
/* device missing or wrong IDENTIFY data, schedule probing */
ehc->i.probe_mask |= (1 << dev->devno);
/* give it just one more chance */
ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1);
case -EIO:
sata_down_spd_limit(ap);
default:
ehc->tries[dev->devno]--;
dnxfer_sel = ATA_DNXFER_ANY;
if (ehc->tries[dev->devno] == 1)
dnxfer_sel = ATA_DNXFER_FORCE_PIO0;
if (down_xfermask && ata_down_xfermask_limit(dev, dnxfer_sel))
ehc->tries[dev->devno] = 0;
if (ehc->tries[dev->devno] == 1) {
/* This is the last chance, better to slow
* down than lose it.
*/
sata_down_spd_limit(ap);
ata_down_xfermask_limit(dev, ATA_DNXFER_PIO);
}
}
if (ata_dev_enabled(dev) && !ehc->tries[dev->devno]) {