aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-10-30 21:17:05 -0400
committerJeff Garzik <jeff@garzik.org>2007-11-03 08:47:26 -0400
commitdfcc173d71b029eb2b10cf99bb5b4e8749e09799 (patch)
treef8b62dc076a082560ffcf94f6f330150766c7ee7
parent08cf69d005acda706bc014c61301993758ce9c5f (diff)
libata: consider errors not associated with commands for speed down
libata EH used to ignore errors not associated with commands when determining whether speed down is necessary or not. This leads to the following problems. * Errors not associated with commands can occur indefinitely without libata EH taking corrective actions. * Upstream link errors don't trigger speed down when PMP is attached to it and commands issued to downstream device trigger errors on the upstream link. This patch makes ata_eh_link_autopsy() consider errors not associated with command for speed down. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/ata/libata-eh.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 7a2e54e92164..ed8813b222a0 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1747,6 +1747,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)
1747{ 1747{
1748 struct ata_port *ap = link->ap; 1748 struct ata_port *ap = link->ap;
1749 struct ata_eh_context *ehc = &link->eh_context; 1749 struct ata_eh_context *ehc = &link->eh_context;
1750 struct ata_device *dev;
1750 unsigned int all_err_mask = 0; 1751 unsigned int all_err_mask = 0;
1751 int tag, is_io = 0; 1752 int tag, is_io = 0;
1752 u32 serror; 1753 u32 serror;
@@ -1818,18 +1819,24 @@ static void ata_eh_link_autopsy(struct ata_link *link)
1818 (!is_io && (all_err_mask & ~AC_ERR_DEV))) 1819 (!is_io && (all_err_mask & ~AC_ERR_DEV)))
1819 ehc->i.action |= ATA_EH_REVALIDATE; 1820 ehc->i.action |= ATA_EH_REVALIDATE;
1820 1821
1821 /* if we have offending qcs and the associated failed device */ 1822 /* If we have offending qcs and the associated failed device,
1823 * perform per-dev EH action only on the offending device.
1824 */
1822 if (ehc->i.dev) { 1825 if (ehc->i.dev) {
1823 /* speed down */
1824 ehc->i.action |= ata_eh_speed_down(ehc->i.dev, is_io,
1825 all_err_mask);
1826
1827 /* perform per-dev EH action only on the offending device */
1828 ehc->i.dev_action[ehc->i.dev->devno] |= 1826 ehc->i.dev_action[ehc->i.dev->devno] |=
1829 ehc->i.action & ATA_EH_PERDEV_MASK; 1827 ehc->i.action & ATA_EH_PERDEV_MASK;
1830 ehc->i.action &= ~ATA_EH_PERDEV_MASK; 1828 ehc->i.action &= ~ATA_EH_PERDEV_MASK;
1831 } 1829 }
1832 1830
1831 /* consider speeding down */
1832 dev = ehc->i.dev;
1833 if (!dev && ata_link_max_devices(link) == 1 &&
1834 ata_dev_enabled(link->device))
1835 dev = link->device;
1836
1837 if (dev)
1838 ehc->i.action |= ata_eh_speed_down(dev, is_io, all_err_mask);
1839
1833 DPRINTK("EXIT\n"); 1840 DPRINTK("EXIT\n");
1834} 1841}
1835 1842