aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-03-20 02:24:11 -0400
committerJeff Garzik <jeff@garzik.org>2007-04-28 14:16:02 -0400
commita51d644af6eb0a93bc383e5f005faa445c87f335 (patch)
treeb1392796d9766e86e7a87d57dd0f7d62e0fa0dfa /drivers/ata
parent55a6adeea4077521b4bba1dfe674f5835157a00b (diff)
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 <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/ahci.c5
-rw-r--r--drivers/ata/libata-core.c16
-rw-r--r--drivers/ata/libata-eh.c4
-rw-r--r--drivers/ata/sata_inic162x.c2
-rw-r--r--drivers/ata/sata_promise.c5
-rw-r--r--drivers/ata/sata_sil24.c5
6 files changed, 17 insertions, 20 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index fb9f69252939..cf39987a31c4 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)
1430 void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR]; 1430 void __iomem *mmio = ap->host->iomap[AHCI_PCI_BAR];
1431 void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); 1431 void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
1432 1432
1433 if (qc->flags & ATA_QCFLAG_FAILED) 1433 if (qc->flags & ATA_QCFLAG_FAILED) {
1434 qc->err_mask |= AC_ERR_OTHER;
1435
1436 if (qc->err_mask) {
1437 /* make DMA engine forget about the failed command */ 1434 /* make DMA engine forget about the failed command */
1438 ahci_stop_engine(port_mmio); 1435 ahci_stop_engine(port_mmio);
1439 ahci_start_engine(port_mmio); 1436 ahci_start_engine(port_mmio);
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 96bf86f67388..2f2884b92434 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,
1270 if (ap->ops->post_internal_cmd) 1270 if (ap->ops->post_internal_cmd)
1271 ap->ops->post_internal_cmd(qc); 1271 ap->ops->post_internal_cmd(qc);
1272 1272
1273 if ((qc->flags & ATA_QCFLAG_FAILED) && !qc->err_mask) { 1273 /* perform minimal error analysis */
1274 if (ata_msg_warn(ap)) 1274 if (qc->flags & ATA_QCFLAG_FAILED) {
1275 ata_dev_printk(dev, KERN_WARNING, 1275 if (qc->result_tf.command & (ATA_ERR | ATA_DF))
1276 "zero err_mask for failed " 1276 qc->err_mask |= AC_ERR_DEV;
1277 "internal command, assuming AC_ERR_OTHER\n"); 1277
1278 qc->err_mask |= AC_ERR_OTHER; 1278 if (!qc->err_mask)
1279 qc->err_mask |= AC_ERR_OTHER;
1280
1281 if (qc->err_mask & ~AC_ERR_OTHER)
1282 qc->err_mask &= ~AC_ERR_OTHER;
1279 } 1283 }
1280 1284
1281 /* finish up */ 1285 /* finish up */
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 185876aba647..0dbee550f9e8 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,
1151 return ATA_EH_SOFTRESET; 1151 return ATA_EH_SOFTRESET;
1152 } 1152 }
1153 1153
1154 if (!(qc->err_mask & AC_ERR_DEV)) 1154 if (stat & (ATA_ERR | ATA_DF))
1155 qc->err_mask |= AC_ERR_DEV;
1156 else
1155 return 0; 1157 return 0;
1156 1158
1157 switch (qc->dev->class) { 1159 switch (qc->dev->class) {
diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c
index 11c3079ab6cc..ca4092aaae5b 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)
488static void inic_post_internal_cmd(struct ata_queued_cmd *qc) 488static void inic_post_internal_cmd(struct ata_queued_cmd *qc)
489{ 489{
490 /* make DMA engine forget about the failed command */ 490 /* make DMA engine forget about the failed command */
491 if (qc->err_mask) 491 if (qc->flags & ATA_QCFLAG_FAILED)
492 inic_reset_port(inic_port_base(qc->ap)); 492 inic_reset_port(inic_port_base(qc->ap));
493} 493}
494 494
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index a7916d72c4ca..8afde4a9ca7e 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)
622{ 622{
623 struct ata_port *ap = qc->ap; 623 struct ata_port *ap = qc->ap;
624 624
625 if (qc->flags & ATA_QCFLAG_FAILED)
626 qc->err_mask |= AC_ERR_OTHER;
627
628 /* make DMA engine forget about the failed command */ 625 /* make DMA engine forget about the failed command */
629 if (qc->err_mask) 626 if (qc->flags & ATA_QCFLAG_FAILED)
630 pdc_reset_port(ap); 627 pdc_reset_port(ap);
631} 628}
632 629
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index 6698c746e624..4f522ec04049 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)
924{ 924{
925 struct ata_port *ap = qc->ap; 925 struct ata_port *ap = qc->ap;
926 926
927 if (qc->flags & ATA_QCFLAG_FAILED)
928 qc->err_mask |= AC_ERR_OTHER;
929
930 /* make DMA engine forget about the failed command */ 927 /* make DMA engine forget about the failed command */
931 if (qc->err_mask) 928 if (qc->flags & ATA_QCFLAG_FAILED)
932 sil24_init_port(ap); 929 sil24_init_port(ap);
933} 930}
934 931