aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-pmp.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/libata-pmp.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/libata-pmp.c')
-rw-r--r--drivers/ata/libata-pmp.c28
1 files changed, 8 insertions, 20 deletions
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
index d91f5090ba9d..8439fc8efdd6 100644
--- a/drivers/ata/libata-pmp.c
+++ b/drivers/ata/libata-pmp.c
@@ -194,15 +194,6 @@ int sata_pmp_std_prereset(struct ata_link *link, unsigned long deadline)
194 const unsigned long *timing = sata_ehc_deb_timing(ehc); 194 const unsigned long *timing = sata_ehc_deb_timing(ehc);
195 int rc; 195 int rc;
196 196
197 /* force HRST? */
198 if (link->flags & ATA_LFLAG_NO_SRST)
199 ehc->i.action |= ATA_EH_HARDRESET;
200
201 /* handle link resume */
202 if ((ehc->i.flags & ATA_EHI_RESUME_LINK) &&
203 (link->flags & ATA_LFLAG_HRST_TO_RESUME))
204 ehc->i.action |= ATA_EH_HARDRESET;
205
206 /* if we're about to do hardreset, nothing more to do */ 197 /* if we're about to do hardreset, nothing more to do */
207 if (ehc->i.action & ATA_EH_HARDRESET) 198 if (ehc->i.action & ATA_EH_HARDRESET)
208 return 0; 199 return 0;
@@ -445,7 +436,7 @@ static int sata_pmp_init_links(struct ata_port *ap, int nr_ports)
445 436
446 link->flags = 0; 437 link->flags = 0;
447 ehc->i.probe_mask |= 1; 438 ehc->i.probe_mask |= 1;
448 ehc->i.action |= ATA_EH_SOFTRESET; 439 ehc->i.action |= ATA_EH_RESET;
449 ehc->i.flags |= ATA_EHI_RESUME_LINK; 440 ehc->i.flags |= ATA_EHI_RESUME_LINK;
450 } 441 }
451 442
@@ -840,13 +831,12 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
840 retry: 831 retry:
841 ehc->classes[0] = ATA_DEV_UNKNOWN; 832 ehc->classes[0] = ATA_DEV_UNKNOWN;
842 833
843 if (ehc->i.action & ATA_EH_RESET_MASK) { 834 if (ehc->i.action & ATA_EH_RESET) {
844 struct ata_link *tlink; 835 struct ata_link *tlink;
845 836
846 ata_eh_freeze_port(ap); 837 ata_eh_freeze_port(ap);
847 838
848 /* reset */ 839 /* reset */
849 ehc->i.action = ATA_EH_HARDRESET;
850 rc = ata_eh_reset(link, 0, prereset, softreset, hardreset, 840 rc = ata_eh_reset(link, 0, prereset, softreset, hardreset,
851 postreset); 841 postreset);
852 if (rc) { 842 if (rc) {
@@ -890,11 +880,11 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
890 reval_failed = 1; 880 reval_failed = 1;
891 881
892 ata_dev_printk(dev, KERN_WARNING, 882 ata_dev_printk(dev, KERN_WARNING,
893 "retrying hardreset%s\n", 883 "retrying reset%s\n",
894 sleep ? " in 5 secs" : ""); 884 sleep ? " in 5 secs" : "");
895 if (sleep) 885 if (sleep)
896 ssleep(5); 886 ssleep(5);
897 ehc->i.action |= ATA_EH_HARDRESET; 887 ehc->i.action |= ATA_EH_RESET;
898 goto retry; 888 goto retry;
899 } else { 889 } else {
900 ata_dev_printk(dev, KERN_ERR, "failed to recover PMP " 890 ata_dev_printk(dev, KERN_ERR, "failed to recover PMP "
@@ -938,10 +928,8 @@ static int sata_pmp_eh_handle_disabled_links(struct ata_port *ap)
938 /* Some PMPs require hardreset sequence to get 928 /* Some PMPs require hardreset sequence to get
939 * SError.N working. 929 * SError.N working.
940 */ 930 */
941 if ((link->flags & ATA_LFLAG_HRST_TO_RESUME) && 931 sata_link_hardreset(link, sata_deb_timing_normal,
942 (link->eh_context.i.flags & ATA_EHI_RESUME_LINK)) 932 jiffies + ATA_TMOUT_INTERNAL_QUICK);
943 sata_link_hardreset(link, sata_deb_timing_normal,
944 jiffies + ATA_TMOUT_INTERNAL_QUICK);
945 933
946 /* unconditionally clear SError.N */ 934 /* unconditionally clear SError.N */
947 rc = sata_scr_write(link, SCR_ERROR, SERR_PHYRDY_CHG); 935 rc = sata_scr_write(link, SCR_ERROR, SERR_PHYRDY_CHG);
@@ -1124,7 +1112,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
1124 1112
1125 link_fail: 1113 link_fail:
1126 if (sata_pmp_handle_link_fail(link, link_tries)) { 1114 if (sata_pmp_handle_link_fail(link, link_tries)) {
1127 pmp_ehc->i.action |= ATA_EH_HARDRESET; 1115 pmp_ehc->i.action |= ATA_EH_RESET;
1128 goto retry; 1116 goto retry;
1129 } 1117 }
1130 1118
@@ -1142,7 +1130,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap,
1142 if (--pmp_tries) { 1130 if (--pmp_tries) {
1143 ata_port_printk(ap, KERN_WARNING, 1131 ata_port_printk(ap, KERN_WARNING,
1144 "failed to recover PMP, retrying in 5 secs\n"); 1132 "failed to recover PMP, retrying in 5 secs\n");
1145 pmp_ehc->i.action |= ATA_EH_HARDRESET; 1133 pmp_ehc->i.action |= ATA_EH_RESET;
1146 ssleep(5); 1134 ssleep(5);
1147 goto retry; 1135 goto retry;
1148 } 1136 }