Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=a51d644af6eb0a93bc383e5f005faa445c87f335
Commit:     a51d644af6eb0a93bc383e5f005faa445c87f335
Parent:     55a6adeea4077521b4bba1dfe674f5835157a00b
Author:     Tejun Heo <[EMAIL PROTECTED]>
AuthorDate: Tue Mar 20 15:24:11 2007 +0900
Committer:  Jeff Garzik <[EMAIL PROTECTED]>
CommitDate: Sat Apr 28 14:16:02 2007 -0400

    libata: improve AC_ERR_DEV handling for ->post_internal_cmd
    
    ->post_internal_cmd is simplified EH for internal commands.  Its
    primary mission is to stop the controller such that no rogue memory
    access or other activities occur after the internal command is
    released.  It may provide error diagnostics by setting qc->err_mask
    but this hasn't been a requirement.
    
    To ignore SETXFER failure for CFA devices, libata needs to know
    whether a command was failed by the device or for any other reason.
    ie. internal command needs to get AC_ERR_DEV right.
    
    This patch makes the following changes to AC_ERR_DEV handling and
    ->post_internal_cmd semantics to accomodate this need and simplify
    callback implementation.
    
    1. As long as the correct bits in the result TF registers are set,
       there is no need to set AC_ERR_DEV explicitly.  libata EH core
       takes care of that for both normal and internal commands.
    
    2. The only requirement for ->post_internal_cmd() is to put the
       controller into quiescent state.  It needs not to set any err_mask.
    
    3. ata_exec_internal_sg() performs minimal error analysis such that
       AC_ERR_DEV is automatically set as long as result_tf is filled
       correctly.
    
    Signed-off-by: Tejun Heo <[EMAIL PROTECTED]>
    Signed-off-by: Jeff Garzik <[EMAIL PROTECTED]>
---
 drivers/ata/ahci.c          |    5 +----
 drivers/ata/libata-core.c   |   16 ++++++++++------
 drivers/ata/libata-eh.c     |    4 +++-
 drivers/ata/sata_inic162x.c |    2 +-
 drivers/ata/sata_promise.c  |    5 +----
 drivers/ata/sata_sil24.c    |    5 +----
 6 files changed, 17 insertions(+), 20 deletions(-)

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index fb9f692..cf39987 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1430,10 +1430,7 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd 
*qc)
        void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
        void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 
-       if (qc->flags & ATA_QCFLAG_FAILED)
-               qc->err_mask |= AC_ERR_OTHER;
-
-       if (qc->err_mask) {
+       if (qc->flags & ATA_QCFLAG_FAILED) {
                /* make DMA engine forget about the failed command */
                ahci_stop_engine(port_mmio);
                ahci_start_engine(port_mmio);
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 96bf86f..2f2884b 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1270,12 +1270,16 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
        if (ap->ops->post_internal_cmd)
                ap->ops->post_internal_cmd(qc);
 
-       if ((qc->flags & ATA_QCFLAG_FAILED) && !qc->err_mask) {
-               if (ata_msg_warn(ap))
-                       ata_dev_printk(dev, KERN_WARNING,
-                               "zero err_mask for failed "
-                               "internal command, assuming AC_ERR_OTHER\n");
-               qc->err_mask |= AC_ERR_OTHER;
+       /* perform minimal error analysis */
+       if (qc->flags & ATA_QCFLAG_FAILED) {
+               if (qc->result_tf.command & (ATA_ERR | ATA_DF))
+                       qc->err_mask |= AC_ERR_DEV;
+
+               if (!qc->err_mask)
+                       qc->err_mask |= AC_ERR_OTHER;
+
+               if (qc->err_mask & ~AC_ERR_OTHER)
+                       qc->err_mask &= ~AC_ERR_OTHER;
        }
 
        /* finish up */
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 185876a..0dbee55 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1151,7 +1151,9 @@ static unsigned int ata_eh_analyze_tf(struct 
ata_queued_cmd *qc,
                return ATA_EH_SOFTRESET;
        }
 
-       if (!(qc->err_mask & AC_ERR_DEV))
+       if (stat & (ATA_ERR | ATA_DF))
+               qc->err_mask |= AC_ERR_DEV;
+       else
                return 0;
 
        switch (qc->dev->class) {
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
index 11c3079..ca4092a 100644
--- a/drivers/ata/sata_inic162x.c
+++ b/drivers/ata/sata_inic162x.c
@@ -488,7 +488,7 @@ static void inic_error_handler(struct ata_port *ap)
 static void inic_post_internal_cmd(struct ata_queued_cmd *qc)
 {
        /* make DMA engine forget about the failed command */
-       if (qc->err_mask)
+       if (qc->flags & ATA_QCFLAG_FAILED)
                inic_reset_port(inic_port_base(qc->ap));
 }
 
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index a7916d7..8afde4a 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -622,11 +622,8 @@ static void pdc_post_internal_cmd(struct ata_queued_cmd 
*qc)
 {
        struct ata_port *ap = qc->ap;
 
-       if (qc->flags & ATA_QCFLAG_FAILED)
-               qc->err_mask |= AC_ERR_OTHER;
-
        /* make DMA engine forget about the failed command */
-       if (qc->err_mask)
+       if (qc->flags & ATA_QCFLAG_FAILED)
                pdc_reset_port(ap);
 }
 
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index 6698c74..4f522ec 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -924,11 +924,8 @@ static void sil24_post_internal_cmd(struct ata_queued_cmd 
*qc)
 {
        struct ata_port *ap = qc->ap;
 
-       if (qc->flags & ATA_QCFLAG_FAILED)
-               qc->err_mask |= AC_ERR_OTHER;
-
        /* make DMA engine forget about the failed command */
-       if (qc->err_mask)
+       if (qc->flags & ATA_QCFLAG_FAILED)
                sil24_init_port(ap);
 }
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to