diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-29 12:11:54 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-29 12:11:54 -0700 |
| commit | 00cda56d39f013cce60f44f1e3da19b87eba5d85 (patch) | |
| tree | 2cfe7bf556562a846ff46a558a31ca1939d2e12c /drivers/ata/libata-eh.c | |
| parent | da8e5aa21e037be02e0752e80b9444ff60185a3f (diff) | |
| parent | ab6fc95f609b372a19e18ea689986846ab1ba29c (diff) | |
Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev
* 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev:
[libata] AHCI: fix newly introduced host-reset bug
[libata] sata_nv: fix SWNCQ enabling
libata: add MAXTOR 7V300F0/VA111900 to NCQ blacklist
libata: no need to speed down if already at PIO0
libata: relocate forcing PIO0 on reset
pata_ns87415: define SUPERIO_IDE_MAX_RETRIES
[libata] Address some checkpatch-spotted issues
[libata] fix 'if(' and similar areas that lack whitespace
libata: implement ata_wait_after_reset()
libata: track SLEEP state and issue SRST to wake it up
libata: relocate and fix post-command processing
Diffstat (limited to 'drivers/ata/libata-eh.c')
| -rw-r--r-- | drivers/ata/libata-eh.c | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 8cb35bb8760..ec55d63cf20 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2083,6 +2083,25 @@ int ata_eh_reset(struct ata_link *link, int classify, ata_eh_about_to_do(link, NULL, ehc->i.action & ATA_EH_RESET_MASK); + ata_link_for_each_dev(dev, link) { + /* If we issue an SRST then an ATA drive (not ATAPI) + * may change configuration and be in PIO0 timing. If + * we do a hard reset (or are coming from power on) + * this is true for ATA or ATAPI. Until we've set a + * suitable controller mode we should not touch the + * bus as we may be talking too fast. + */ + dev->pio_mode = XFER_PIO_0; + + /* If the controller has a pio mode setup function + * then use it to set the chipset to rights. Don't + * touch the DMA setup as that will be dealt with when + * configuring devices. + */ + if (ap->ops->set_piomode) + ap->ops->set_piomode(ap, dev); + } + /* Determine which reset to use and record in ehc->i.action. * prereset() may examine and modify it. */ @@ -2208,9 +2227,11 @@ int ata_eh_reset(struct ata_link *link, int classify, ata_link_for_each_dev(dev, link) { /* After the reset, the device state is PIO 0 * and the controller state is undefined. - * Record the mode. + * Reset also wakes up drives from sleeping + * mode. */ dev->pio_mode = XFER_PIO_0; + dev->flags &= ~ATA_DFLAG_SLEEPING; if (ata_link_offline(link)) continue; @@ -2416,7 +2437,7 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err) /* give it just one more chance */ ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1); case -EIO: - if (ehc->tries[dev->devno] == 1) { + if (ehc->tries[dev->devno] == 1 && dev->pio_mode > XFER_PIO_0) { /* This is the last chance, better to slow * down than lose it. */ |
