diff options
Diffstat (limited to 'drivers/ata/sata_mv.c')
-rw-r--r-- | drivers/ata/sata_mv.c | 40 |
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; |