aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/ahci.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/ahci.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/ahci.c')
-rw-r--r--drivers/ata/ahci.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index b1eb4e24c86a..f6bbd52b1547 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1663,7 +1663,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
1663 u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK); 1663 u32 *unk = (u32 *)(pp->rx_fis + RX_FIS_UNK);
1664 1664
1665 active_ehi->err_mask |= AC_ERR_HSM; 1665 active_ehi->err_mask |= AC_ERR_HSM;
1666 active_ehi->action |= ATA_EH_SOFTRESET; 1666 active_ehi->action |= ATA_EH_RESET;
1667 ata_ehi_push_desc(active_ehi, 1667 ata_ehi_push_desc(active_ehi,
1668 "unknown FIS %08x %08x %08x %08x" , 1668 "unknown FIS %08x %08x %08x %08x" ,
1669 unk[0], unk[1], unk[2], unk[3]); 1669 unk[0], unk[1], unk[2], unk[3]);
@@ -1671,19 +1671,19 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat)
1671 1671
1672 if (ap->nr_pmp_links && (irq_stat & PORT_IRQ_BAD_PMP)) { 1672 if (ap->nr_pmp_links && (irq_stat & PORT_IRQ_BAD_PMP)) {
1673 active_ehi->err_mask |= AC_ERR_HSM; 1673 active_ehi->err_mask |= AC_ERR_HSM;
1674 active_ehi->action |= ATA_EH_SOFTRESET; 1674 active_ehi->action |= ATA_EH_RESET;
1675 ata_ehi_push_desc(active_ehi, "incorrect PMP"); 1675 ata_ehi_push_desc(active_ehi, "incorrect PMP");
1676 } 1676 }
1677 1677
1678 if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) { 1678 if (irq_stat & (PORT_IRQ_HBUS_ERR | PORT_IRQ_HBUS_DATA_ERR)) {
1679 host_ehi->err_mask |= AC_ERR_HOST_BUS; 1679 host_ehi->err_mask |= AC_ERR_HOST_BUS;
1680 host_ehi->action |= ATA_EH_SOFTRESET; 1680 host_ehi->action |= ATA_EH_RESET;
1681 ata_ehi_push_desc(host_ehi, "host bus error"); 1681 ata_ehi_push_desc(host_ehi, "host bus error");
1682 } 1682 }
1683 1683
1684 if (irq_stat & PORT_IRQ_IF_ERR) { 1684 if (irq_stat & PORT_IRQ_IF_ERR) {
1685 host_ehi->err_mask |= AC_ERR_ATA_BUS; 1685 host_ehi->err_mask |= AC_ERR_ATA_BUS;
1686 host_ehi->action |= ATA_EH_SOFTRESET; 1686 host_ehi->action |= ATA_EH_RESET;
1687 ata_ehi_push_desc(host_ehi, "interface fatal error"); 1687 ata_ehi_push_desc(host_ehi, "interface fatal error");
1688 } 1688 }
1689 1689
@@ -1771,7 +1771,7 @@ static void ahci_port_intr(struct ata_port *ap)
1771 /* while resetting, invalid completions are expected */ 1771 /* while resetting, invalid completions are expected */
1772 if (unlikely(rc < 0 && !resetting)) { 1772 if (unlikely(rc < 0 && !resetting)) {
1773 ehi->err_mask |= AC_ERR_HSM; 1773 ehi->err_mask |= AC_ERR_HSM;
1774 ehi->action |= ATA_EH_SOFTRESET; 1774 ehi->action |= ATA_EH_RESET;
1775 ata_port_freeze(ap); 1775 ata_port_freeze(ap);
1776 } 1776 }
1777} 1777}