summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2009-07-20 11:21:15 +1000
committerStephen Rothwell <sfr@canb.auug.org.au>2009-07-20 11:21:15 +1000
commitf54da60a37827355523995b28cf1efa9ee9481ec (patch)
tree2aa08be75302bd826fa97793766f664158d49e1b
parentb59a9124d1fa716377f60d5c583d5542758ca096 (diff)
parent10d4be2bbb6c017bcbda80fb342dbade51468bc6 (diff)
Merge commit 'libata/NEXT'
-rw-r--r--drivers/ata/libata-eh.c6
-rw-r--r--drivers/ata/sata_sil.c13
2 files changed, 17 insertions, 2 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 1a07c061f644..fe327821bd00 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -999,7 +999,9 @@ static void __ata_port_freeze(struct ata_port *ap)
* ata_port_freeze - abort & freeze port
* @ap: ATA port to freeze
*
- * Abort and freeze @ap.
+ * Abort and freeze @ap. The freeze operation must be called
+ * first, because some hardware requires special operations
+ * before the taskfile registers are accessible.
*
* LOCKING:
* spin_lock_irqsave(host lock)
@@ -1013,8 +1015,8 @@ int ata_port_freeze(struct ata_port *ap)
WARN_ON(!ap->ops->error_handler);
- nr_aborted = ata_port_abort(ap);
__ata_port_freeze(ap);
+ nr_aborted = ata_port_abort(ap);
return nr_aborted;
}
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c
index 030ec079b184..d41dcebb746a 100644
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -565,6 +565,19 @@ static void sil_freeze(struct ata_port *ap)
tmp |= SIL_MASK_IDE0_INT << ap->port_no;
writel(tmp, mmio_base + SIL_SYSCFG);
readl(mmio_base + SIL_SYSCFG); /* flush */
+
+ /* Ensure DMA_ENABLE is off.
+ *
+ * This is because the controller will not give us access to the
+ * taskfile registers while a DMA is in progress
+ */
+ iowrite8(ioread8(ap->ioaddr.bmdma_addr) & ~SIL_DMA_ENABLE,
+ ap->ioaddr.bmdma_addr);
+
+ /* According to ata_bmdma_stop, an HDMA transition requires
+ * on PIO cycle. But we can't read a taskfile register.
+ */
+ ioread8(ap->ioaddr.bmdma_addr);
}
static void sil_thaw(struct ata_port *ap)