Gitweb:     
http://git.kernel.org/linus/;a=commit;h=b03e66a6be91f8389fcd902ab6c1563db1c9c06b
Commit:     b03e66a6be91f8389fcd902ab6c1563db1c9c06b
Parent:     cd705d5ad49bb8894dda2726dcaef8f63ddeba43
Author:     David Milburn <[email protected]>
AuthorDate: Mon Oct 29 18:00:22 2012 -0500
Committer:  Jeff Garzik <[email protected]>
CommitDate: Thu Nov 15 23:54:41 2012 -0500

    sata_svw: check DMA start bit before reset
    
    If kdump is triggered with pending IO, controller may not respond causing
    kdump to fail.
    
    http://marc.info/?l=linux-ide&m=133032255424658&w=2
    
    During error recovery ata_do_dev_read_id never completes due hang
    in mmio_insw.
    
    ata_do_dev_read_id
     ata_sff_data_xfer
      ioread16_rep
       mmio_insw
    
    if DMA start bit is cleared before reset, PIO command is successful
    and kdump succeeds.
    
    Signed-off-by: David Milburn <[email protected]>
    Signed-off-by: Jeff Garzik <[email protected]>
---
 drivers/ata/sata_svw.c |   35 +++++++++++++++++++++++++++++++++++
 1 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c
index 44a4256..08608de 100644
--- a/drivers/ata/sata_svw.c
+++ b/drivers/ata/sata_svw.c
@@ -142,6 +142,39 @@ static int k2_sata_scr_write(struct ata_link *link,
         return 0;
 }
 
+static int k2_sata_softreset(struct ata_link *link,
+                             unsigned int *class, unsigned long deadline)
+{
+        u8 dmactl;
+        void __iomem *mmio = link->ap->ioaddr.bmdma_addr;
+
+        dmactl = readb(mmio + ATA_DMA_CMD);
+
+        /* Clear the start bit */
+        if (dmactl & ATA_DMA_START) {
+                dmactl &= ~ATA_DMA_START;
+                writeb(dmactl, mmio + ATA_DMA_CMD);
+        }
+
+        return ata_sff_softreset(link, class, deadline);
+}
+
+static int k2_sata_hardreset(struct ata_link *link,
+                             unsigned int *class, unsigned long deadline)
+{
+        u8 dmactl;
+        void __iomem *mmio = link->ap->ioaddr.bmdma_addr;
+
+        dmactl = readb(mmio + ATA_DMA_CMD);
+
+        /* Clear the start bit */
+        if (dmactl & ATA_DMA_START) {
+                dmactl &= ~ATA_DMA_START;
+                writeb(dmactl, mmio + ATA_DMA_CMD);
+        }
+
+        return sata_sff_hardreset(link, class, deadline);
+}
 
 static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
 {
@@ -346,6 +379,8 @@ static struct scsi_host_template k2_sata_sht = {
 
 static struct ata_port_operations k2_sata_ops = {
         .inherits                = &ata_bmdma_port_ops,
+        .softreset              = k2_sata_softreset,
+        .hardreset              = k2_sata_hardreset,
         .sff_tf_load                = k2_sata_tf_load,
         .sff_tf_read                = k2_sata_tf_read,
         .sff_check_status        = k2_stat_check_status,
--
--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to