aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/sata_mv.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2008-01-23 10:05:14 -0500
committerJeff Garzik <jgarzik@redhat.com>2008-04-17 15:44:15 -0400
commitcf48062658e7ab3bc55e10c65676c3c73c16f8bf (patch)
tree9a50a016ceb6051d8a30a43ea39f2a4d3d25570e /drivers/ata/sata_mv.c
parent4b119e21d0c66c22e8ca03df05d9de623d0eb50f (diff)
libata: prefer hardreset
When both soft and hard resets are available, libata preferred softreset till now. The logic behind it was to be softer to devices; however, this doesn't really help much. Rationales for the change: * BIOS may freeze lock certain things during boot and softreset can't unlock those. This by itself is okay but during operation PHY event or other error conditions can trigger hardreset and the device may end up with different configuration. For example, after a hardreset, previously unlockable HPA can be unlocked resulting in different device size and thus revalidation failure. Similar condition can occur during or after resume. * Certain ATAPI devices require hardreset to recover after certain error conditions. On PATA, this is done by issuing the DEVICE RESET command. On SATA, COMRESET has equivalent effect. The problem is that DEVICE RESET needs its own execution protocol. For SFF controllers with bare TF access, it can be easily implemented but more advanced controllers (e.g. ahci and sata_sil24) require specialized implementations. Simply using hardreset solves the problem nicely. * COMRESET initialization sequence is the norm in SATA land and many SATA devices don't work properly if only SRST is used. For example, some PMPs behave this way and libata works around by always issuing hardreset if the host supports PMP. Like the above example, libata has developed a number of mechanisms aiming to promote softreset to hardreset if softreset is not going to work. This approach is time consuming and error prone. Also, note that, dependingon how you read the specs, it could be argued that PMP fan-out ports require COMRESET to start operation. In fact, all the PMPs on the market except one don't work properly if COMRESET is not issued to fan-out ports after PMP reset. * COMRESET is an integral part of SATA connection and any working device should be able to handle COMRESET properly. After all, it's the way to signal hardreset during reboot. This is the most used and recommended (at least by the ahci spec) method of resetting devices. So, this patch makes libata prefer hardreset over softreset by making the following changes. * Rename ATA_EH_RESET_MASK to ATA_EH_RESET and use it whereever ATA_EH_{SOFT|HARD}RESET used to be used. ATA_EH_{SOFT|HARD}RESET is now only used to tell prereset whether soft or hard reset will be issued. * Strip out now unneeded promote-to-hardreset logics from ata_eh_reset(), ata_std_prereset(), sata_pmp_std_prereset() and other places. Signed-off-by: Tejun Heo <htejun@gmail.com>
Diffstat (limited to 'drivers/ata/sata_mv.c')
-rw-r--r--drivers/ata/sata_mv.c31
1 files changed, 8 insertions, 23 deletions
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 6ebebde8454..a4944c8ad46 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -1524,14 +1524,14 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
1524 EDMA_ERR_CRQB_PAR | EDMA_ERR_CRPB_PAR | 1524 EDMA_ERR_CRQB_PAR | EDMA_ERR_CRPB_PAR |
1525 EDMA_ERR_INTRL_PAR)) { 1525 EDMA_ERR_INTRL_PAR)) {
1526 err_mask |= AC_ERR_ATA_BUS; 1526 err_mask |= AC_ERR_ATA_BUS;
1527 action |= ATA_EH_HARDRESET; 1527 action |= ATA_EH_RESET;
1528 ata_ehi_push_desc(ehi, "parity error"); 1528 ata_ehi_push_desc(ehi, "parity error");
1529 } 1529 }
1530 if (edma_err_cause & (EDMA_ERR_DEV_DCON | EDMA_ERR_DEV_CON)) { 1530 if (edma_err_cause & (EDMA_ERR_DEV_DCON | EDMA_ERR_DEV_CON)) {
1531 ata_ehi_hotplugged(ehi); 1531 ata_ehi_hotplugged(ehi);
1532 ata_ehi_push_desc(ehi, edma_err_cause & EDMA_ERR_DEV_DCON ? 1532 ata_ehi_push_desc(ehi, edma_err_cause & EDMA_ERR_DEV_DCON ?
1533 "dev disconnect" : "dev connect"); 1533 "dev disconnect" : "dev connect");
1534 action |= ATA_EH_HARDRESET; 1534 action |= ATA_EH_RESET;
1535 } 1535 }
1536 1536
1537 if (IS_GEN_I(hpriv)) { 1537 if (IS_GEN_I(hpriv)) {
@@ -1555,7 +1555,7 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
1555 sata_scr_read(&ap->link, SCR_ERROR, &serr); 1555 sata_scr_read(&ap->link, SCR_ERROR, &serr);
1556 sata_scr_write_flush(&ap->link, SCR_ERROR, serr); 1556 sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
1557 err_mask = AC_ERR_ATA_BUS; 1557 err_mask = AC_ERR_ATA_BUS;
1558 action |= ATA_EH_HARDRESET; 1558 action |= ATA_EH_RESET;
1559 } 1559 }
1560 } 1560 }
1561 1561
@@ -1564,7 +1564,7 @@ static void mv_err_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
1564 1564
1565 if (!err_mask) { 1565 if (!err_mask) {
1566 err_mask = AC_ERR_OTHER; 1566 err_mask = AC_ERR_OTHER;
1567 action |= ATA_EH_HARDRESET; 1567 action |= ATA_EH_RESET;
1568 } 1568 }
1569 1569
1570 ehi->serror |= serr; 1570 ehi->serror |= serr;
@@ -1780,7 +1780,7 @@ static void mv_pci_error(struct ata_host *host, void __iomem *mmio)
1780 ata_ehi_push_desc(ehi, 1780 ata_ehi_push_desc(ehi,
1781 "PCI err cause 0x%08x", err_cause); 1781 "PCI err cause 0x%08x", err_cause);
1782 err_mask = AC_ERR_HOST_BUS; 1782 err_mask = AC_ERR_HOST_BUS;
1783 ehi->action = ATA_EH_HARDRESET; 1783 ehi->action = ATA_EH_RESET;
1784 qc = ata_qc_from_tag(ap, ap->link.active_tag); 1784 qc = ata_qc_from_tag(ap, ap->link.active_tag);
1785 if (qc) 1785 if (qc)
1786 qc->err_mask |= err_mask; 1786 qc->err_mask |= err_mask;
@@ -2449,28 +2449,13 @@ static int mv_prereset(struct ata_link *link, unsigned long deadline)
2449{ 2449{
2450 struct ata_port *ap = link->ap; 2450 struct ata_port *ap = link->ap;
2451 struct mv_port_priv *pp = ap->private_data; 2451 struct mv_port_priv *pp = ap->private_data;
2452 struct ata_eh_context *ehc = &link->eh_context;
2453 int rc;
2454 2452
2455 rc = mv_stop_dma(ap); 2453 mv_stop_dma(ap);
2456 if (rc)
2457 ehc->i.action |= ATA_EH_HARDRESET;
2458 2454
2459 if (!(pp->pp_flags & MV_PP_FLAG_HAD_A_RESET)) { 2455 if (!(pp->pp_flags & MV_PP_FLAG_HAD_A_RESET))
2460 pp->pp_flags |= MV_PP_FLAG_HAD_A_RESET; 2456 pp->pp_flags |= MV_PP_FLAG_HAD_A_RESET;
2461 ehc->i.action |= ATA_EH_HARDRESET;
2462 }
2463
2464 /* if we're about to do hardreset, nothing more to do */
2465 if (ehc->i.action & ATA_EH_HARDRESET)
2466 return 0;
2467
2468 if (ata_link_online(link))
2469 rc = ata_wait_ready(ap, deadline);
2470 else
2471 rc = -ENODEV;
2472 2457
2473 return rc; 2458 return 0;
2474} 2459}
2475 2460
2476static int mv_hardreset(struct ata_link *link, unsigned int *class, 2461static int mv_hardreset(struct ata_link *link, unsigned int *class,