diff options
Diffstat (limited to 'drivers/ata/libata-eh.c')
-rw-r--r-- | drivers/ata/libata-eh.c | 204 |
1 files changed, 190 insertions, 14 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 9aa62a0754f6..ac6ceed4bb60 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
@@ -56,6 +56,7 @@ enum { | |||
56 | */ | 56 | */ |
57 | enum { | 57 | enum { |
58 | ATA_EH_PRERESET_TIMEOUT = 10 * HZ, | 58 | ATA_EH_PRERESET_TIMEOUT = 10 * HZ, |
59 | ATA_EH_FASTDRAIN_INTERVAL = 3 * HZ, | ||
59 | }; | 60 | }; |
60 | 61 | ||
61 | /* The following table determines how we sequence resets. Each entry | 62 | /* The following table determines how we sequence resets. Each entry |
@@ -85,6 +86,71 @@ static void ata_eh_handle_port_resume(struct ata_port *ap) | |||
85 | { } | 86 | { } |
86 | #endif /* CONFIG_PM */ | 87 | #endif /* CONFIG_PM */ |
87 | 88 | ||
89 | static void __ata_ehi_pushv_desc(struct ata_eh_info *ehi, const char *fmt, | ||
90 | va_list args) | ||
91 | { | ||
92 | ehi->desc_len += vscnprintf(ehi->desc + ehi->desc_len, | ||
93 | ATA_EH_DESC_LEN - ehi->desc_len, | ||
94 | fmt, args); | ||
95 | } | ||
96 | |||
97 | /** | ||
98 | * __ata_ehi_push_desc - push error description without adding separator | ||
99 | * @ehi: target EHI | ||
100 | * @fmt: printf format string | ||
101 | * | ||
102 | * Format string according to @fmt and append it to @ehi->desc. | ||
103 | * | ||
104 | * LOCKING: | ||
105 | * spin_lock_irqsave(host lock) | ||
106 | */ | ||
107 | void __ata_ehi_push_desc(struct ata_eh_info *ehi, const char *fmt, ...) | ||
108 | { | ||
109 | va_list args; | ||
110 | |||
111 | va_start(args, fmt); | ||
112 | __ata_ehi_pushv_desc(ehi, fmt, args); | ||
113 | va_end(args); | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * ata_ehi_push_desc - push error description with separator | ||
118 | * @ehi: target EHI | ||
119 | * @fmt: printf format string | ||
120 | * | ||
121 | * Format string according to @fmt and append it to @ehi->desc. | ||
122 | * If @ehi->desc is not empty, ", " is added in-between. | ||
123 | * | ||
124 | * LOCKING: | ||
125 | * spin_lock_irqsave(host lock) | ||
126 | */ | ||
127 | void ata_ehi_push_desc(struct ata_eh_info *ehi, const char *fmt, ...) | ||
128 | { | ||
129 | va_list args; | ||
130 | |||
131 | if (ehi->desc_len) | ||
132 | __ata_ehi_push_desc(ehi, ", "); | ||
133 | |||
134 | va_start(args, fmt); | ||
135 | __ata_ehi_pushv_desc(ehi, fmt, args); | ||
136 | va_end(args); | ||
137 | } | ||
138 | |||
139 | /** | ||
140 | * ata_ehi_clear_desc - clean error description | ||
141 | * @ehi: target EHI | ||
142 | * | ||
143 | * Clear @ehi->desc. | ||
144 | * | ||
145 | * LOCKING: | ||
146 | * spin_lock_irqsave(host lock) | ||
147 | */ | ||
148 | void ata_ehi_clear_desc(struct ata_eh_info *ehi) | ||
149 | { | ||
150 | ehi->desc[0] = '\0'; | ||
151 | ehi->desc_len = 0; | ||
152 | } | ||
153 | |||
88 | static void ata_ering_record(struct ata_ering *ering, int is_io, | 154 | static void ata_ering_record(struct ata_ering *ering, int is_io, |
89 | unsigned int err_mask) | 155 | unsigned int err_mask) |
90 | { | 156 | { |
@@ -296,6 +362,9 @@ void ata_scsi_error(struct Scsi_Host *host) | |||
296 | repeat: | 362 | repeat: |
297 | /* invoke error handler */ | 363 | /* invoke error handler */ |
298 | if (ap->ops->error_handler) { | 364 | if (ap->ops->error_handler) { |
365 | /* kill fast drain timer */ | ||
366 | del_timer_sync(&ap->fastdrain_timer); | ||
367 | |||
299 | /* process port resume request */ | 368 | /* process port resume request */ |
300 | ata_eh_handle_port_resume(ap); | 369 | ata_eh_handle_port_resume(ap); |
301 | 370 | ||
@@ -511,6 +580,94 @@ void ata_eng_timeout(struct ata_port *ap) | |||
511 | DPRINTK("EXIT\n"); | 580 | DPRINTK("EXIT\n"); |
512 | } | 581 | } |
513 | 582 | ||
583 | static int ata_eh_nr_in_flight(struct ata_port *ap) | ||
584 | { | ||
585 | unsigned int tag; | ||
586 | int nr = 0; | ||
587 | |||
588 | /* count only non-internal commands */ | ||
589 | for (tag = 0; tag < ATA_MAX_QUEUE - 1; tag++) | ||
590 | if (ata_qc_from_tag(ap, tag)) | ||
591 | nr++; | ||
592 | |||
593 | return nr; | ||
594 | } | ||
595 | |||
596 | void ata_eh_fastdrain_timerfn(unsigned long arg) | ||
597 | { | ||
598 | struct ata_port *ap = (void *)arg; | ||
599 | unsigned long flags; | ||
600 | int cnt; | ||
601 | |||
602 | spin_lock_irqsave(ap->lock, flags); | ||
603 | |||
604 | cnt = ata_eh_nr_in_flight(ap); | ||
605 | |||
606 | /* are we done? */ | ||
607 | if (!cnt) | ||
608 | goto out_unlock; | ||
609 | |||
610 | if (cnt == ap->fastdrain_cnt) { | ||
611 | unsigned int tag; | ||
612 | |||
613 | /* No progress during the last interval, tag all | ||
614 | * in-flight qcs as timed out and freeze the port. | ||
615 | */ | ||
616 | for (tag = 0; tag < ATA_MAX_QUEUE - 1; tag++) { | ||
617 | struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag); | ||
618 | if (qc) | ||
619 | qc->err_mask |= AC_ERR_TIMEOUT; | ||
620 | } | ||
621 | |||
622 | ata_port_freeze(ap); | ||
623 | } else { | ||
624 | /* some qcs have finished, give it another chance */ | ||
625 | ap->fastdrain_cnt = cnt; | ||
626 | ap->fastdrain_timer.expires = | ||
627 | jiffies + ATA_EH_FASTDRAIN_INTERVAL; | ||
628 | add_timer(&ap->fastdrain_timer); | ||
629 | } | ||
630 | |||
631 | out_unlock: | ||
632 | spin_unlock_irqrestore(ap->lock, flags); | ||
633 | } | ||
634 | |||
635 | /** | ||
636 | * ata_eh_set_pending - set ATA_PFLAG_EH_PENDING and activate fast drain | ||
637 | * @ap: target ATA port | ||
638 | * @fastdrain: activate fast drain | ||
639 | * | ||
640 | * Set ATA_PFLAG_EH_PENDING and activate fast drain if @fastdrain | ||
641 | * is non-zero and EH wasn't pending before. Fast drain ensures | ||
642 | * that EH kicks in in timely manner. | ||
643 | * | ||
644 | * LOCKING: | ||
645 | * spin_lock_irqsave(host lock) | ||
646 | */ | ||
647 | static void ata_eh_set_pending(struct ata_port *ap, int fastdrain) | ||
648 | { | ||
649 | int cnt; | ||
650 | |||
651 | /* already scheduled? */ | ||
652 | if (ap->pflags & ATA_PFLAG_EH_PENDING) | ||
653 | return; | ||
654 | |||
655 | ap->pflags |= ATA_PFLAG_EH_PENDING; | ||
656 | |||
657 | if (!fastdrain) | ||
658 | return; | ||
659 | |||
660 | /* do we have in-flight qcs? */ | ||
661 | cnt = ata_eh_nr_in_flight(ap); | ||
662 | if (!cnt) | ||
663 | return; | ||
664 | |||
665 | /* activate fast drain */ | ||
666 | ap->fastdrain_cnt = cnt; | ||
667 | ap->fastdrain_timer.expires = jiffies + ATA_EH_FASTDRAIN_INTERVAL; | ||
668 | add_timer(&ap->fastdrain_timer); | ||
669 | } | ||
670 | |||
514 | /** | 671 | /** |
515 | * ata_qc_schedule_eh - schedule qc for error handling | 672 | * ata_qc_schedule_eh - schedule qc for error handling |
516 | * @qc: command to schedule error handling for | 673 | * @qc: command to schedule error handling for |
@@ -528,7 +685,7 @@ void ata_qc_schedule_eh(struct ata_queued_cmd *qc) | |||
528 | WARN_ON(!ap->ops->error_handler); | 685 | WARN_ON(!ap->ops->error_handler); |
529 | 686 | ||
530 | qc->flags |= ATA_QCFLAG_FAILED; | 687 | qc->flags |= ATA_QCFLAG_FAILED; |
531 | qc->ap->pflags |= ATA_PFLAG_EH_PENDING; | 688 | ata_eh_set_pending(ap, 1); |
532 | 689 | ||
533 | /* The following will fail if timeout has already expired. | 690 | /* The following will fail if timeout has already expired. |
534 | * ata_scsi_error() takes care of such scmds on EH entry. | 691 | * ata_scsi_error() takes care of such scmds on EH entry. |
@@ -555,7 +712,7 @@ void ata_port_schedule_eh(struct ata_port *ap) | |||
555 | if (ap->pflags & ATA_PFLAG_INITIALIZING) | 712 | if (ap->pflags & ATA_PFLAG_INITIALIZING) |
556 | return; | 713 | return; |
557 | 714 | ||
558 | ap->pflags |= ATA_PFLAG_EH_PENDING; | 715 | ata_eh_set_pending(ap, 1); |
559 | scsi_schedule_eh(ap->scsi_host); | 716 | scsi_schedule_eh(ap->scsi_host); |
560 | 717 | ||
561 | DPRINTK("port EH scheduled\n"); | 718 | DPRINTK("port EH scheduled\n"); |
@@ -579,6 +736,9 @@ int ata_port_abort(struct ata_port *ap) | |||
579 | 736 | ||
580 | WARN_ON(!ap->ops->error_handler); | 737 | WARN_ON(!ap->ops->error_handler); |
581 | 738 | ||
739 | /* we're gonna abort all commands, no need for fast drain */ | ||
740 | ata_eh_set_pending(ap, 0); | ||
741 | |||
582 | for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { | 742 | for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { |
583 | struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag); | 743 | struct ata_queued_cmd *qc = ata_qc_from_tag(ap, tag); |
584 | 744 | ||
@@ -1130,7 +1290,7 @@ static void ata_eh_analyze_ncq_error(struct ata_port *ap) | |||
1130 | /* we've got the perpetrator, condemn it */ | 1290 | /* we've got the perpetrator, condemn it */ |
1131 | qc = __ata_qc_from_tag(ap, tag); | 1291 | qc = __ata_qc_from_tag(ap, tag); |
1132 | memcpy(&qc->result_tf, &tf, sizeof(tf)); | 1292 | memcpy(&qc->result_tf, &tf, sizeof(tf)); |
1133 | qc->err_mask |= AC_ERR_DEV; | 1293 | qc->err_mask |= AC_ERR_DEV | AC_ERR_NCQ; |
1134 | ehc->i.err_mask &= ~AC_ERR_DEV; | 1294 | ehc->i.err_mask &= ~AC_ERR_DEV; |
1135 | } | 1295 | } |
1136 | 1296 | ||
@@ -1413,8 +1573,12 @@ static void ata_eh_autopsy(struct ata_port *ap) | |||
1413 | if (rc == 0) { | 1573 | if (rc == 0) { |
1414 | ehc->i.serror |= serror; | 1574 | ehc->i.serror |= serror; |
1415 | ata_eh_analyze_serror(ap); | 1575 | ata_eh_analyze_serror(ap); |
1416 | } else if (rc != -EOPNOTSUPP) | 1576 | } else if (rc != -EOPNOTSUPP) { |
1577 | /* SError read failed, force hardreset and probing */ | ||
1578 | ata_ehi_schedule_probe(&ehc->i); | ||
1417 | ehc->i.action |= ATA_EH_HARDRESET; | 1579 | ehc->i.action |= ATA_EH_HARDRESET; |
1580 | ehc->i.err_mask |= AC_ERR_OTHER; | ||
1581 | } | ||
1418 | 1582 | ||
1419 | /* analyze NCQ failure */ | 1583 | /* analyze NCQ failure */ |
1420 | ata_eh_analyze_ncq_error(ap); | 1584 | ata_eh_analyze_ncq_error(ap); |
@@ -1524,14 +1688,14 @@ static void ata_eh_report(struct ata_port *ap) | |||
1524 | ehc->i.err_mask, ap->sactive, ehc->i.serror, | 1688 | ehc->i.err_mask, ap->sactive, ehc->i.serror, |
1525 | ehc->i.action, frozen); | 1689 | ehc->i.action, frozen); |
1526 | if (desc) | 1690 | if (desc) |
1527 | ata_dev_printk(ehc->i.dev, KERN_ERR, "(%s)\n", desc); | 1691 | ata_dev_printk(ehc->i.dev, KERN_ERR, "%s\n", desc); |
1528 | } else { | 1692 | } else { |
1529 | ata_port_printk(ap, KERN_ERR, "exception Emask 0x%x " | 1693 | ata_port_printk(ap, KERN_ERR, "exception Emask 0x%x " |
1530 | "SAct 0x%x SErr 0x%x action 0x%x%s\n", | 1694 | "SAct 0x%x SErr 0x%x action 0x%x%s\n", |
1531 | ehc->i.err_mask, ap->sactive, ehc->i.serror, | 1695 | ehc->i.err_mask, ap->sactive, ehc->i.serror, |
1532 | ehc->i.action, frozen); | 1696 | ehc->i.action, frozen); |
1533 | if (desc) | 1697 | if (desc) |
1534 | ata_port_printk(ap, KERN_ERR, "(%s)\n", desc); | 1698 | ata_port_printk(ap, KERN_ERR, "%s\n", desc); |
1535 | } | 1699 | } |
1536 | 1700 | ||
1537 | for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { | 1701 | for (tag = 0; tag < ATA_MAX_QUEUE; tag++) { |
@@ -1551,7 +1715,7 @@ static void ata_eh_report(struct ata_port *ap) | |||
1551 | "cmd %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x " | 1715 | "cmd %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x " |
1552 | "tag %d cdb 0x%x data %u %s\n " | 1716 | "tag %d cdb 0x%x data %u %s\n " |
1553 | "res %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x " | 1717 | "res %02x/%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x/%02x " |
1554 | "Emask 0x%x (%s)\n", | 1718 | "Emask 0x%x (%s)%s\n", |
1555 | cmd->command, cmd->feature, cmd->nsect, | 1719 | cmd->command, cmd->feature, cmd->nsect, |
1556 | cmd->lbal, cmd->lbam, cmd->lbah, | 1720 | cmd->lbal, cmd->lbam, cmd->lbah, |
1557 | cmd->hob_feature, cmd->hob_nsect, | 1721 | cmd->hob_feature, cmd->hob_nsect, |
@@ -1562,7 +1726,8 @@ static void ata_eh_report(struct ata_port *ap) | |||
1562 | res->lbal, res->lbam, res->lbah, | 1726 | res->lbal, res->lbam, res->lbah, |
1563 | res->hob_feature, res->hob_nsect, | 1727 | res->hob_feature, res->hob_nsect, |
1564 | res->hob_lbal, res->hob_lbam, res->hob_lbah, | 1728 | res->hob_lbal, res->hob_lbam, res->hob_lbah, |
1565 | res->device, qc->err_mask, ata_err_string(qc->err_mask)); | 1729 | res->device, qc->err_mask, ata_err_string(qc->err_mask), |
1730 | qc->err_mask & AC_ERR_NCQ ? " <F>" : ""); | ||
1566 | } | 1731 | } |
1567 | } | 1732 | } |
1568 | 1733 | ||
@@ -1648,7 +1813,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify, | |||
1648 | } else | 1813 | } else |
1649 | ata_port_printk(ap, KERN_ERR, | 1814 | ata_port_printk(ap, KERN_ERR, |
1650 | "prereset failed (errno=%d)\n", rc); | 1815 | "prereset failed (errno=%d)\n", rc); |
1651 | return rc; | 1816 | goto out; |
1652 | } | 1817 | } |
1653 | } | 1818 | } |
1654 | 1819 | ||
@@ -1661,7 +1826,8 @@ static int ata_eh_reset(struct ata_port *ap, int classify, | |||
1661 | /* prereset told us not to reset, bang classes and return */ | 1826 | /* prereset told us not to reset, bang classes and return */ |
1662 | for (i = 0; i < ATA_MAX_DEVICES; i++) | 1827 | for (i = 0; i < ATA_MAX_DEVICES; i++) |
1663 | classes[i] = ATA_DEV_NONE; | 1828 | classes[i] = ATA_DEV_NONE; |
1664 | return 0; | 1829 | rc = 0; |
1830 | goto out; | ||
1665 | } | 1831 | } |
1666 | 1832 | ||
1667 | /* did prereset() screw up? if so, fix up to avoid oopsing */ | 1833 | /* did prereset() screw up? if so, fix up to avoid oopsing */ |
@@ -1697,7 +1863,8 @@ static int ata_eh_reset(struct ata_port *ap, int classify, | |||
1697 | ata_port_printk(ap, KERN_ERR, | 1863 | ata_port_printk(ap, KERN_ERR, |
1698 | "follow-up softreset required " | 1864 | "follow-up softreset required " |
1699 | "but no softreset avaliable\n"); | 1865 | "but no softreset avaliable\n"); |
1700 | return -EINVAL; | 1866 | rc = -EINVAL; |
1867 | goto out; | ||
1701 | } | 1868 | } |
1702 | 1869 | ||
1703 | ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK); | 1870 | ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK); |
@@ -1707,7 +1874,8 @@ static int ata_eh_reset(struct ata_port *ap, int classify, | |||
1707 | classes[0] == ATA_DEV_UNKNOWN) { | 1874 | classes[0] == ATA_DEV_UNKNOWN) { |
1708 | ata_port_printk(ap, KERN_ERR, | 1875 | ata_port_printk(ap, KERN_ERR, |
1709 | "classification failed\n"); | 1876 | "classification failed\n"); |
1710 | return -EINVAL; | 1877 | rc = -EINVAL; |
1878 | goto out; | ||
1711 | } | 1879 | } |
1712 | } | 1880 | } |
1713 | 1881 | ||
@@ -1724,7 +1892,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify, | |||
1724 | schedule_timeout_uninterruptible(delta); | 1892 | schedule_timeout_uninterruptible(delta); |
1725 | } | 1893 | } |
1726 | 1894 | ||
1727 | if (reset == hardreset && | 1895 | if (rc == -EPIPE || |
1728 | try == ARRAY_SIZE(ata_eh_reset_timeouts) - 1) | 1896 | try == ARRAY_SIZE(ata_eh_reset_timeouts) - 1) |
1729 | sata_down_spd_limit(ap); | 1897 | sata_down_spd_limit(ap); |
1730 | if (hardreset) | 1898 | if (hardreset) |
@@ -1733,12 +1901,18 @@ static int ata_eh_reset(struct ata_port *ap, int classify, | |||
1733 | } | 1901 | } |
1734 | 1902 | ||
1735 | if (rc == 0) { | 1903 | if (rc == 0) { |
1904 | u32 sstatus; | ||
1905 | |||
1736 | /* After the reset, the device state is PIO 0 and the | 1906 | /* After the reset, the device state is PIO 0 and the |
1737 | * controller state is undefined. Record the mode. | 1907 | * controller state is undefined. Record the mode. |
1738 | */ | 1908 | */ |
1739 | for (i = 0; i < ATA_MAX_DEVICES; i++) | 1909 | for (i = 0; i < ATA_MAX_DEVICES; i++) |
1740 | ap->device[i].pio_mode = XFER_PIO_0; | 1910 | ap->device[i].pio_mode = XFER_PIO_0; |
1741 | 1911 | ||
1912 | /* record current link speed */ | ||
1913 | if (sata_scr_read(ap, SCR_STATUS, &sstatus) == 0) | ||
1914 | ap->sata_spd = (sstatus >> 4) & 0xf; | ||
1915 | |||
1742 | if (postreset) | 1916 | if (postreset) |
1743 | postreset(ap, classes); | 1917 | postreset(ap, classes); |
1744 | 1918 | ||
@@ -1746,7 +1920,9 @@ static int ata_eh_reset(struct ata_port *ap, int classify, | |||
1746 | ata_eh_done(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK); | 1920 | ata_eh_done(ap, NULL, ehc->i.action & ATA_EH_RESET_MASK); |
1747 | ehc->i.action |= ATA_EH_REVALIDATE; | 1921 | ehc->i.action |= ATA_EH_REVALIDATE; |
1748 | } | 1922 | } |
1749 | 1923 | out: | |
1924 | /* clear hotplug flag */ | ||
1925 | ehc->i.flags &= ~ATA_EHI_HOTPLUGGED; | ||
1750 | return rc; | 1926 | return rc; |
1751 | } | 1927 | } |
1752 | 1928 | ||