aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorMark Lord <liml@rtr.ca>2008-04-19 15:07:49 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-04-25 01:26:14 -0400
commit8d07379d251ab24d937e6cb0748b71106dddbc74 (patch)
tree4c8388db13465e9c9a523114189cfdbc1d2830c1 /drivers/ata
parent8f767f8a02e6c65d393fd0f2ca19a91c9898cc2d (diff)
sata_mv: leave SError bits untouched in mv_err_intr
Here it is again, minus the checkpatch.pl complaint: Rework mv_err_intr() to leave the SError bits as-is, so that libata-eh has a chance to see/use them. We originally thought that clearing them here was necessary before writing back to edma_err_cause (per the Marvell datasheets), but we will end up reseting the chip regardless in those cases. Signed-off-by: Mark Lord <mlord@pobox.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/sata_mv.c40
1 files changed, 19 insertions, 21 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 944359256959..4fa54805eb41 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -1523,13 +1523,11 @@ static void mv_unexpected_intr(struct ata_port *ap)
1523/** 1523/**
1524 * mv_err_intr - Handle error interrupts on the port 1524 * mv_err_intr - Handle error interrupts on the port
1525 * @ap: ATA channel to manipulate 1525 * @ap: ATA channel to manipulate
1526 * @reset_allowed: bool: 0 == don't trigger from reset here 1526 * @qc: affected command (non-NCQ), or NULL
1527 * 1527 *
1528 * In most cases, just clear the interrupt and move on. However, 1528 * Most cases require a full reset of the chip's state machine,
1529 * some cases require an eDMA reset, which also performs a COMRESET. 1529 * which also performs a COMRESET.
1530 * The SERR case requires a clear of pending errors in the SATA 1530 * Also, if the port disabled DMA, update our cached copy to match.
1531 * SERROR register. Finally, if the port disabled DMA,
1532 * update our cached copy to match.
1533 * 1531 *
1534 * LOCKING: 1532 * LOCKING:
1535 * Inherited from caller. 1533 * Inherited from caller.
@@ -1540,21 +1538,18 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
1540 u32 edma_err_cause, eh_freeze_mask, serr = 0; 1538 u32 edma_err_cause, eh_freeze_mask, serr = 0;
1541 struct mv_port_priv *pp = ap->private_data; 1539 struct mv_port_priv *pp = ap->private_data;
1542 struct mv_host_priv *hpriv = ap->host->private_data; 1540 struct mv_host_priv *hpriv = ap->host->private_data;
1543 unsigned int edma_enabled = (pp->pp_flags & MV_PP_FLAG_EDMA_EN);
1544 unsigned int action = 0, err_mask = 0; 1541 unsigned int action = 0, err_mask = 0;
1545 struct ata_eh_info *ehi = &ap->link.eh_info; 1542 struct ata_eh_info *ehi = &ap->link.eh_info;
1546 1543
1547 ata_ehi_clear_desc(ehi); 1544 ata_ehi_clear_desc(ehi);
1548 1545
1549 if (!edma_enabled) { 1546 /*
1550 /* just a guess: do we need to do this? should we 1547 * Read and clear the err_cause bits. This won't actually
1551 * expand this, and do it in all cases? 1548 * clear for some errors (eg. SError), but we will be doing
1552 */ 1549 * a hard reset in those cases regardless, which *will* clear it.
1553 sata_scr_read(&ap->link, SCR_ERROR, &serr); 1550 */
1554 sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
1555 }
1556
1557 edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); 1551 edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
1552 writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
1558 1553
1559 ata_ehi_push_desc(ehi, "edma_err_cause=%08x", edma_err_cause); 1554 ata_ehi_push_desc(ehi, "edma_err_cause=%08x", edma_err_cause);
1560 1555
@@ -1594,16 +1589,19 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
1594 ata_ehi_push_desc(ehi, "EDMA self-disable"); 1589 ata_ehi_push_desc(ehi, "EDMA self-disable");
1595 } 1590 }
1596 if (edma_err_cause & EDMA_ERR_SERR) { 1591 if (edma_err_cause & EDMA_ERR_SERR) {
1597 sata_scr_read(&ap->link, SCR_ERROR, &serr); 1592 /*
1598 sata_scr_write_flush(&ap->link, SCR_ERROR, serr); 1593 * Ensure that we read our own SCR, not a pmp link SCR:
1599 err_mask = AC_ERR_ATA_BUS; 1594 */
1595 ap->ops->scr_read(ap, SCR_ERROR, &serr);
1596 /*
1597 * Don't clear SError here; leave it for libata-eh:
1598 */
1599 ata_ehi_push_desc(ehi, "SError=%08x", serr);
1600 err_mask |= AC_ERR_ATA_BUS;
1600 action |= ATA_EH_RESET; 1601 action |= ATA_EH_RESET;
1601 } 1602 }
1602 } 1603 }
1603 1604
1604 /* Clear EDMA now that SERR cleanup done */
1605 writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
1606
1607 if (!err_mask) { 1605 if (!err_mask) {
1608 err_mask = AC_ERR_OTHER; 1606 err_mask = AC_ERR_OTHER;
1609 action |= ATA_EH_RESET; 1607 action |= ATA_EH_RESET;