aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/sata_sil24.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_sil24.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_sil24.c')
-rw-r--r--drivers/ata/sata_sil24.c54
1 files changed, 27 insertions, 27 deletions
diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c
index df7988df7908..aa8d0323c9bb 100644
--- a/drivers/ata/sata_sil24.c
+++ b/drivers/ata/sata_sil24.c
@@ -286,45 +286,45 @@ static struct sil24_cerr_info {
286 "device error via D2H FIS" }, 286 "device error via D2H FIS" },
287 [PORT_CERR_SDB] = { AC_ERR_DEV, 0, 287 [PORT_CERR_SDB] = { AC_ERR_DEV, 0,
288 "device error via SDB FIS" }, 288 "device error via SDB FIS" },
289 [PORT_CERR_DATA] = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET, 289 [PORT_CERR_DATA] = { AC_ERR_ATA_BUS, ATA_EH_RESET,
290 "error in data FIS" }, 290 "error in data FIS" },
291 [PORT_CERR_SEND] = { AC_ERR_ATA_BUS, ATA_EH_SOFTRESET, 291 [PORT_CERR_SEND] = { AC_ERR_ATA_BUS, ATA_EH_RESET,
292 "failed to transmit command FIS" }, 292 "failed to transmit command FIS" },
293 [PORT_CERR_INCONSISTENT] = { AC_ERR_HSM, ATA_EH_SOFTRESET, 293 [PORT_CERR_INCONSISTENT] = { AC_ERR_HSM, ATA_EH_RESET,
294 "protocol mismatch" }, 294 "protocol mismatch" },
295 [PORT_CERR_DIRECTION] = { AC_ERR_HSM, ATA_EH_SOFTRESET, 295 [PORT_CERR_DIRECTION] = { AC_ERR_HSM, ATA_EH_RESET,
296 "data directon mismatch" }, 296 "data directon mismatch" },
297 [PORT_CERR_UNDERRUN] = { AC_ERR_HSM, ATA_EH_SOFTRESET, 297 [PORT_CERR_UNDERRUN] = { AC_ERR_HSM, ATA_EH_RESET,
298 "ran out of SGEs while writing" }, 298 "ran out of SGEs while writing" },
299 [PORT_CERR_OVERRUN] = { AC_ERR_HSM, ATA_EH_SOFTRESET, 299 [PORT_CERR_OVERRUN] = { AC_ERR_HSM, ATA_EH_RESET,
300 "ran out of SGEs while reading" }, 300 "ran out of SGEs while reading" },
301 [PORT_CERR_PKT_PROT] = { AC_ERR_HSM, ATA_EH_SOFTRESET, 301 [PORT_CERR_PKT_PROT] = { AC_ERR_HSM, ATA_EH_RESET,
302 "invalid data directon for ATAPI CDB" }, 302 "invalid data directon for ATAPI CDB" },
303 [PORT_CERR_SGT_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET, 303 [PORT_CERR_SGT_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_RESET,
304 "SGT not on qword boundary" }, 304 "SGT not on qword boundary" },
305 [PORT_CERR_SGT_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, 305 [PORT_CERR_SGT_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
306 "PCI target abort while fetching SGT" }, 306 "PCI target abort while fetching SGT" },
307 [PORT_CERR_SGT_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, 307 [PORT_CERR_SGT_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
308 "PCI master abort while fetching SGT" }, 308 "PCI master abort while fetching SGT" },
309 [PORT_CERR_SGT_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, 309 [PORT_CERR_SGT_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
310 "PCI parity error while fetching SGT" }, 310 "PCI parity error while fetching SGT" },
311 [PORT_CERR_CMD_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_SOFTRESET, 311 [PORT_CERR_CMD_BOUNDARY] = { AC_ERR_SYSTEM, ATA_EH_RESET,
312 "PRB not on qword boundary" }, 312 "PRB not on qword boundary" },
313 [PORT_CERR_CMD_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, 313 [PORT_CERR_CMD_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
314 "PCI target abort while fetching PRB" }, 314 "PCI target abort while fetching PRB" },
315 [PORT_CERR_CMD_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, 315 [PORT_CERR_CMD_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
316 "PCI master abort while fetching PRB" }, 316 "PCI master abort while fetching PRB" },
317 [PORT_CERR_CMD_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, 317 [PORT_CERR_CMD_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
318 "PCI parity error while fetching PRB" }, 318 "PCI parity error while fetching PRB" },
319 [PORT_CERR_XFR_UNDEF] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, 319 [PORT_CERR_XFR_UNDEF] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
320 "undefined error while transferring data" }, 320 "undefined error while transferring data" },
321 [PORT_CERR_XFR_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, 321 [PORT_CERR_XFR_TGTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
322 "PCI target abort while transferring data" }, 322 "PCI target abort while transferring data" },
323 [PORT_CERR_XFR_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, 323 [PORT_CERR_XFR_MSTABRT] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
324 "PCI master abort while transferring data" }, 324 "PCI master abort while transferring data" },
325 [PORT_CERR_XFR_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_SOFTRESET, 325 [PORT_CERR_XFR_PCIPERR] = { AC_ERR_HOST_BUS, ATA_EH_RESET,
326 "PCI parity error while transferring data" }, 326 "PCI parity error while transferring data" },
327 [PORT_CERR_SENDSERVICE] = { AC_ERR_HSM, ATA_EH_SOFTRESET, 327 [PORT_CERR_SENDSERVICE] = { AC_ERR_HSM, ATA_EH_RESET,
328 "FIS received while sending service FIS" }, 328 "FIS received while sending service FIS" },
329}; 329};
330 330
@@ -616,7 +616,7 @@ static int sil24_init_port(struct ata_port *ap)
616 616
617 if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY) { 617 if ((tmp & (PORT_CS_INIT | PORT_CS_RDY)) != PORT_CS_RDY) {
618 pp->do_port_rst = 1; 618 pp->do_port_rst = 1;
619 ap->link.eh_context.i.action |= ATA_EH_HARDRESET; 619 ap->link.eh_context.i.action |= ATA_EH_RESET;
620 return -EIO; 620 return -EIO;
621 } 621 }
622 622
@@ -1022,7 +1022,7 @@ static void sil24_error_intr(struct ata_port *ap)
1022 1022
1023 if (irq_stat & PORT_IRQ_UNK_FIS) { 1023 if (irq_stat & PORT_IRQ_UNK_FIS) {
1024 ehi->err_mask |= AC_ERR_HSM; 1024 ehi->err_mask |= AC_ERR_HSM;
1025 ehi->action |= ATA_EH_SOFTRESET; 1025 ehi->action |= ATA_EH_RESET;
1026 ata_ehi_push_desc(ehi, "unknown FIS"); 1026 ata_ehi_push_desc(ehi, "unknown FIS");
1027 freeze = 1; 1027 freeze = 1;
1028 } 1028 }
@@ -1043,7 +1043,7 @@ static void sil24_error_intr(struct ata_port *ap)
1043 */ 1043 */
1044 if (ap->nr_active_links >= 3) { 1044 if (ap->nr_active_links >= 3) {
1045 ehi->err_mask |= AC_ERR_OTHER; 1045 ehi->err_mask |= AC_ERR_OTHER;
1046 ehi->action |= ATA_EH_HARDRESET; 1046 ehi->action |= ATA_EH_RESET;
1047 ata_ehi_push_desc(ehi, "PMP DMA CS errata"); 1047 ata_ehi_push_desc(ehi, "PMP DMA CS errata");
1048 pp->do_port_rst = 1; 1048 pp->do_port_rst = 1;
1049 freeze = 1; 1049 freeze = 1;
@@ -1064,7 +1064,7 @@ static void sil24_error_intr(struct ata_port *ap)
1064 irq_stat); 1064 irq_stat);
1065 } else { 1065 } else {
1066 err_mask |= AC_ERR_HSM; 1066 err_mask |= AC_ERR_HSM;
1067 action |= ATA_EH_HARDRESET; 1067 action |= ATA_EH_RESET;
1068 freeze = 1; 1068 freeze = 1;
1069 } 1069 }
1070 } else 1070 } else
@@ -1078,12 +1078,12 @@ static void sil24_error_intr(struct ata_port *ap)
1078 if (ci && ci->desc) { 1078 if (ci && ci->desc) {
1079 err_mask |= ci->err_mask; 1079 err_mask |= ci->err_mask;
1080 action |= ci->action; 1080 action |= ci->action;
1081 if (action & ATA_EH_RESET_MASK) 1081 if (action & ATA_EH_RESET)
1082 freeze = 1; 1082 freeze = 1;
1083 ata_ehi_push_desc(ehi, "%s", ci->desc); 1083 ata_ehi_push_desc(ehi, "%s", ci->desc);
1084 } else { 1084 } else {
1085 err_mask |= AC_ERR_OTHER; 1085 err_mask |= AC_ERR_OTHER;
1086 action |= ATA_EH_SOFTRESET; 1086 action |= ATA_EH_RESET;
1087 freeze = 1; 1087 freeze = 1;
1088 ata_ehi_push_desc(ehi, "unknown command error %d", 1088 ata_ehi_push_desc(ehi, "unknown command error %d",
1089 cerr); 1089 cerr);
@@ -1153,7 +1153,7 @@ static inline void sil24_host_intr(struct ata_port *ap)
1153 if (rc < 0) { 1153 if (rc < 0) {
1154 struct ata_eh_info *ehi = &ap->link.eh_info; 1154 struct ata_eh_info *ehi = &ap->link.eh_info;
1155 ehi->err_mask |= AC_ERR_HSM; 1155 ehi->err_mask |= AC_ERR_HSM;
1156 ehi->action |= ATA_EH_SOFTRESET; 1156 ehi->action |= ATA_EH_RESET;
1157 ata_port_freeze(ap); 1157 ata_port_freeze(ap);
1158 return; 1158 return;
1159 } 1159 }