diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-01-12 20:56:20 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-01-12 20:56:20 -0800 |
commit | 2d13c8f0682bd38c74e89a76cc550f0324b610ba (patch) | |
tree | 8e2286479c18f5ee076d26ee44ff03b44d38a299 | |
parent | 1f0e14bbc065c88ddb68fec42b317f487cc85410 (diff) | |
parent | 5040ab67a2c6d5710ba497dc52a8f7035729d7b0 (diff) |
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev
* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev:
libata: retry link resume if necessary
ata_piix: enable 32bit PIO on SATA piix
sata_promise: don't classify overruns as HSM errors
-rw-r--r-- | drivers/ata/ata_piix.c | 2 | ||||
-rw-r--r-- | drivers/ata/libata-core.c | 38 | ||||
-rw-r--r-- | drivers/ata/sata_promise.c | 2 | ||||
-rw-r--r-- | include/linux/libata.h | 3 |
4 files changed, 36 insertions, 9 deletions
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 19136a7e1064..6f3f2257d0f0 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -329,7 +329,7 @@ static struct ata_port_operations ich_pata_ops = { }; static struct ata_port_operations piix_sata_ops = { - .inherits = &ata_bmdma_port_ops, + .inherits = &ata_bmdma32_port_ops, }; static struct ata_port_operations piix_sidpr_sata_ops = { diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 22ff51bdbc8a..6728328f3bea 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -3790,21 +3790,45 @@ int sata_link_debounce(struct ata_link *link, const unsigned long *params, int sata_link_resume(struct ata_link *link, const unsigned long *params, unsigned long deadline) { + int tries = ATA_LINK_RESUME_TRIES; u32 scontrol, serror; int rc; if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol))) return rc; - scontrol = (scontrol & 0x0f0) | 0x300; + /* + * Writes to SControl sometimes get ignored under certain + * controllers (ata_piix SIDPR). Make sure DET actually is + * cleared. + */ + do { + scontrol = (scontrol & 0x0f0) | 0x300; + if ((rc = sata_scr_write(link, SCR_CONTROL, scontrol))) + return rc; + /* + * Some PHYs react badly if SStatus is pounded + * immediately after resuming. Delay 200ms before + * debouncing. + */ + msleep(200); - if ((rc = sata_scr_write(link, SCR_CONTROL, scontrol))) - return rc; + /* is SControl restored correctly? */ + if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol))) + return rc; + } while ((scontrol & 0xf0f) != 0x300 && --tries); - /* Some PHYs react badly if SStatus is pounded immediately - * after resuming. Delay 200ms before debouncing. - */ - msleep(200); + if ((scontrol & 0xf0f) != 0x300) { + ata_link_printk(link, KERN_ERR, + "failed to resume link (SControl %X)\n", + scontrol); + return 0; + } + + if (tries < ATA_LINK_RESUME_TRIES) + ata_link_printk(link, KERN_WARNING, + "link resume succeeded after %d retries\n", + ATA_LINK_RESUME_TRIES - tries); if ((rc = sata_link_debounce(link, params, deadline))) return rc; diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 07d8d00b4d34..63306285c843 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -862,7 +862,7 @@ static void pdc_error_intr(struct ata_port *ap, struct ata_queued_cmd *qc, if (port_status & PDC_DRIVE_ERR) ac_err_mask |= AC_ERR_DEV; if (port_status & (PDC_OVERRUN_ERR | PDC_UNDERRUN_ERR)) - ac_err_mask |= AC_ERR_HSM; + ac_err_mask |= AC_ERR_OTHER; if (port_status & (PDC2_ATA_HBA_ERR | PDC2_ATA_DMA_CNT_ERR)) ac_err_mask |= AC_ERR_ATA_BUS; if (port_status & (PDC_PH_ERR | PDC_SH_ERR | PDC_DH_ERR | PDC2_HTO_ERR diff --git a/include/linux/libata.h b/include/linux/libata.h index 6a9c4ddd3d95..73112250862c 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -354,6 +354,9 @@ enum { /* max tries if error condition is still set after ->error_handler */ ATA_EH_MAX_TRIES = 5, + /* sometimes resuming a link requires several retries */ + ATA_LINK_RESUME_TRIES = 5, + /* how hard are we gonna try to probe/recover devices */ ATA_PROBE_MAX_TRIES = 3, ATA_EH_DEV_TRIES = 3, |