[PATCH] libata: implement PM EH actions

Implement two PM per-dev EH actions - ATA_EH_SUSPEND and
ATA_EH_RESUME. Each action puts the target device into suspended mode
and resumes from it respectively.

Once a device is put to suspended mode, no EH operations other than
RESUME is allowed on the device. The device will stay suspended till
it gets resumed and thus reset and revalidated. To implement this, a
new device state helper - ata_dev_ready() - is implemented and used in
EH action implementations to make them operate only on attached &
running devices.

If all possible devices on a port are suspended, reset is skipped too.
This prevents spurious events including hotplug events from disrupting
suspended devices.

Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>

authored by Tejun Heo and committed by Jeff Garzik 02670bf3 c0b6c037

+198 -4
+3 -2
drivers/scsi/libata-core.c
··· 2146 * return error code and failing device on failure. 2147 */ 2148 for (i = 0; i < ATA_MAX_DEVICES; i++) { 2149 - if (ata_dev_enabled(&ap->device[i])) { 2150 ap->ops->set_mode(ap); 2151 break; 2152 } ··· 2212 for (i = 0; i < ATA_MAX_DEVICES; i++) { 2213 dev = &ap->device[i]; 2214 2215 - if (!ata_dev_enabled(dev)) 2216 continue; 2217 2218 rc = ata_dev_set_mode(dev);
··· 2146 * return error code and failing device on failure. 2147 */ 2148 for (i = 0; i < ATA_MAX_DEVICES; i++) { 2149 + if (ata_dev_ready(&ap->device[i])) { 2150 ap->ops->set_mode(ap); 2151 break; 2152 } ··· 2212 for (i = 0; i < ATA_MAX_DEVICES; i++) { 2213 dev = &ap->device[i]; 2214 2215 + /* don't udpate suspended devices' xfer mode */ 2216 + if (!ata_dev_ready(dev)) 2217 continue; 2218 2219 rc = ata_dev_set_mode(dev);
+184 -1
drivers/scsi/libata-eh.c
··· 1610 dev = &ap->device[i]; 1611 action = ata_eh_dev_action(dev); 1612 1613 - if (action & ATA_EH_REVALIDATE && ata_dev_enabled(dev)) { 1614 if (ata_port_offline(ap)) { 1615 rc = -EIO; 1616 break; ··· 1653 return rc; 1654 } 1655 1656 static int ata_port_nr_enabled(struct ata_port *ap) 1657 { 1658 int i, cnt = 0; ··· 1836 struct ata_eh_context *ehc = &ap->eh_context; 1837 int i; 1838 1839 if (ap->pflags & ATA_PFLAG_FROZEN || ata_port_nr_enabled(ap)) 1840 return 0; 1841 ··· 1922 if (ap->pflags & ATA_PFLAG_UNLOADING) 1923 goto out; 1924 1925 /* skip EH if possible. */ 1926 if (ata_eh_skip_recovery(ap)) 1927 ehc->i.action = 0; ··· 1952 if (rc) 1953 goto dev_fail; 1954 1955 /* configure transfer mode if the port has been reset */ 1956 if (ehc->i.flags & ATA_EHI_DID_RESET) { 1957 rc = ata_set_mode(ap, &dev); ··· 1965 goto dev_fail; 1966 } 1967 } 1968 1969 goto out; 1970
··· 1610 dev = &ap->device[i]; 1611 action = ata_eh_dev_action(dev); 1612 1613 + if (action & ATA_EH_REVALIDATE && ata_dev_ready(dev)) { 1614 if (ata_port_offline(ap)) { 1615 rc = -EIO; 1616 break; ··· 1653 return rc; 1654 } 1655 1656 + /** 1657 + * ata_eh_suspend - handle suspend EH action 1658 + * @ap: target host port 1659 + * @r_failed_dev: result parameter to indicate failing device 1660 + * 1661 + * Handle suspend EH action. Disk devices are spinned down and 1662 + * other types of devices are just marked suspended. Once 1663 + * suspended, no EH action to the device is allowed until it is 1664 + * resumed. 1665 + * 1666 + * LOCKING: 1667 + * Kernel thread context (may sleep). 1668 + * 1669 + * RETURNS: 1670 + * 0 on success, -errno otherwise 1671 + */ 1672 + static int ata_eh_suspend(struct ata_port *ap, struct ata_device **r_failed_dev) 1673 + { 1674 + struct ata_device *dev; 1675 + int i, rc = 0; 1676 + 1677 + DPRINTK("ENTER\n"); 1678 + 1679 + for (i = 0; i < ATA_MAX_DEVICES; i++) { 1680 + unsigned long flags; 1681 + unsigned int action, err_mask; 1682 + 1683 + dev = &ap->device[i]; 1684 + action = ata_eh_dev_action(dev); 1685 + 1686 + if (!ata_dev_enabled(dev) || !(action & ATA_EH_SUSPEND)) 1687 + continue; 1688 + 1689 + WARN_ON(dev->flags & ATA_DFLAG_SUSPENDED); 1690 + 1691 + ata_eh_about_to_do(ap, dev, ATA_EH_SUSPEND); 1692 + 1693 + if (dev->class == ATA_DEV_ATA && !(action & ATA_EH_PM_FREEZE)) { 1694 + /* flush cache */ 1695 + rc = ata_flush_cache(dev); 1696 + if (rc) 1697 + break; 1698 + 1699 + /* spin down */ 1700 + err_mask = ata_do_simple_cmd(dev, ATA_CMD_STANDBYNOW1); 1701 + if (err_mask) { 1702 + ata_dev_printk(dev, KERN_ERR, "failed to " 1703 + "spin down (err_mask=0x%x)\n", 1704 + err_mask); 1705 + rc = -EIO; 1706 + break; 1707 + } 1708 + } 1709 + 1710 + spin_lock_irqsave(ap->lock, flags); 1711 + dev->flags |= ATA_DFLAG_SUSPENDED; 1712 + spin_unlock_irqrestore(ap->lock, flags); 1713 + 1714 + ata_eh_done(ap, dev, ATA_EH_SUSPEND); 1715 + } 1716 + 1717 + if (rc) 1718 + *r_failed_dev = dev; 1719 + 1720 + DPRINTK("EXIT\n"); 1721 + return 0; 1722 + } 1723 + 1724 + /** 1725 + * ata_eh_prep_resume - prep for resume EH action 1726 + * @ap: target host port 1727 + * 1728 + * Clear SUSPENDED in preparation for scheduled resume actions. 1729 + * This allows other parts of EH to access the devices being 1730 + * resumed. 1731 + * 1732 + * LOCKING: 1733 + * Kernel thread context (may sleep). 1734 + */ 1735 + static void ata_eh_prep_resume(struct ata_port *ap) 1736 + { 1737 + struct ata_device *dev; 1738 + unsigned long flags; 1739 + int i; 1740 + 1741 + DPRINTK("ENTER\n"); 1742 + 1743 + for (i = 0; i < ATA_MAX_DEVICES; i++) { 1744 + unsigned int action; 1745 + 1746 + dev = &ap->device[i]; 1747 + action = ata_eh_dev_action(dev); 1748 + 1749 + if (!ata_dev_enabled(dev) || !(action & ATA_EH_RESUME)) 1750 + continue; 1751 + 1752 + spin_lock_irqsave(ap->lock, flags); 1753 + dev->flags &= ~ATA_DFLAG_SUSPENDED; 1754 + spin_unlock_irqrestore(ap->lock, flags); 1755 + } 1756 + 1757 + DPRINTK("EXIT\n"); 1758 + } 1759 + 1760 + /** 1761 + * ata_eh_resume - handle resume EH action 1762 + * @ap: target host port 1763 + * @r_failed_dev: result parameter to indicate failing device 1764 + * 1765 + * Handle resume EH action. Target devices are already reset and 1766 + * revalidated. Spinning up is the only operation left. 1767 + * 1768 + * LOCKING: 1769 + * Kernel thread context (may sleep). 1770 + * 1771 + * RETURNS: 1772 + * 0 on success, -errno otherwise 1773 + */ 1774 + static int ata_eh_resume(struct ata_port *ap, struct ata_device **r_failed_dev) 1775 + { 1776 + struct ata_device *dev; 1777 + int i, rc = 0; 1778 + 1779 + DPRINTK("ENTER\n"); 1780 + 1781 + for (i = 0; i < ATA_MAX_DEVICES; i++) { 1782 + unsigned int action, err_mask; 1783 + 1784 + dev = &ap->device[i]; 1785 + action = ata_eh_dev_action(dev); 1786 + 1787 + if (!ata_dev_enabled(dev) || !(action & ATA_EH_RESUME)) 1788 + continue; 1789 + 1790 + ata_eh_about_to_do(ap, dev, ATA_EH_RESUME); 1791 + 1792 + if (dev->class == ATA_DEV_ATA && !(action & ATA_EH_PM_FREEZE)) { 1793 + err_mask = ata_do_simple_cmd(dev, 1794 + ATA_CMD_IDLEIMMEDIATE); 1795 + if (err_mask) { 1796 + ata_dev_printk(dev, KERN_ERR, "failed to " 1797 + "spin up (err_mask=0x%x)\n", 1798 + err_mask); 1799 + rc = -EIO; 1800 + break; 1801 + } 1802 + } 1803 + 1804 + ata_eh_done(ap, dev, ATA_EH_RESUME); 1805 + } 1806 + 1807 + if (rc) 1808 + *r_failed_dev = dev; 1809 + 1810 + DPRINTK("EXIT\n"); 1811 + return 0; 1812 + } 1813 + 1814 static int ata_port_nr_enabled(struct ata_port *ap) 1815 { 1816 int i, cnt = 0; ··· 1678 struct ata_eh_context *ehc = &ap->eh_context; 1679 int i; 1680 1681 + /* skip if all possible devices are suspended */ 1682 + for (i = 0; i < ata_port_max_devices(ap); i++) { 1683 + struct ata_device *dev = &ap->device[i]; 1684 + 1685 + if (ata_dev_absent(dev) || ata_dev_ready(dev)) 1686 + break; 1687 + } 1688 + 1689 + if (i == ata_port_max_devices(ap)) 1690 + return 1; 1691 + 1692 + /* always thaw frozen port and recover failed devices */ 1693 if (ap->pflags & ATA_PFLAG_FROZEN || ata_port_nr_enabled(ap)) 1694 return 0; 1695 ··· 1752 if (ap->pflags & ATA_PFLAG_UNLOADING) 1753 goto out; 1754 1755 + /* prep for resume */ 1756 + ata_eh_prep_resume(ap); 1757 + 1758 /* skip EH if possible. */ 1759 if (ata_eh_skip_recovery(ap)) 1760 ehc->i.action = 0; ··· 1779 if (rc) 1780 goto dev_fail; 1781 1782 + /* resume devices */ 1783 + rc = ata_eh_resume(ap, &dev); 1784 + if (rc) 1785 + goto dev_fail; 1786 + 1787 /* configure transfer mode if the port has been reset */ 1788 if (ehc->i.flags & ATA_EHI_DID_RESET) { 1789 rc = ata_set_mode(ap, &dev); ··· 1787 goto dev_fail; 1788 } 1789 } 1790 + 1791 + /* suspend devices */ 1792 + rc = ata_eh_suspend(ap, &dev); 1793 + if (rc) 1794 + goto dev_fail; 1795 1796 goto out; 1797
+11 -1
include/linux/libata.h
··· 131 ATA_DFLAG_CFG_MASK = (1 << 8) - 1, 132 133 ATA_DFLAG_PIO = (1 << 8), /* device currently in PIO mode */ 134 ATA_DFLAG_INIT_MASK = (1 << 16) - 1, 135 136 ATA_DFLAG_DETACH = (1 << 16), ··· 254 ATA_EH_REVALIDATE = (1 << 0), 255 ATA_EH_SOFTRESET = (1 << 1), 256 ATA_EH_HARDRESET = (1 << 2), 257 258 ATA_EH_RESET_MASK = ATA_EH_SOFTRESET | ATA_EH_HARDRESET, 259 - ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE, 260 261 /* ata_eh_info->flags */ 262 ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */ ··· 947 static inline unsigned int ata_dev_absent(const struct ata_device *dev) 948 { 949 return ata_class_absent(dev->class); 950 } 951 952 /*
··· 131 ATA_DFLAG_CFG_MASK = (1 << 8) - 1, 132 133 ATA_DFLAG_PIO = (1 << 8), /* device currently in PIO mode */ 134 + ATA_DFLAG_SUSPENDED = (1 << 9), /* device suspended */ 135 ATA_DFLAG_INIT_MASK = (1 << 16) - 1, 136 137 ATA_DFLAG_DETACH = (1 << 16), ··· 253 ATA_EH_REVALIDATE = (1 << 0), 254 ATA_EH_SOFTRESET = (1 << 1), 255 ATA_EH_HARDRESET = (1 << 2), 256 + ATA_EH_SUSPEND = (1 << 3), 257 + ATA_EH_RESUME = (1 << 4), 258 + ATA_EH_PM_FREEZE = (1 << 5), 259 260 ATA_EH_RESET_MASK = ATA_EH_SOFTRESET | ATA_EH_HARDRESET, 261 + ATA_EH_PERDEV_MASK = ATA_EH_REVALIDATE | ATA_EH_SUSPEND | 262 + ATA_EH_RESUME | ATA_EH_PM_FREEZE, 263 264 /* ata_eh_info->flags */ 265 ATA_EHI_HOTPLUGGED = (1 << 0), /* could have been hotplugged */ ··· 942 static inline unsigned int ata_dev_absent(const struct ata_device *dev) 943 { 944 return ata_class_absent(dev->class); 945 + } 946 + 947 + static inline unsigned int ata_dev_ready(const struct ata_device *dev) 948 + { 949 + return ata_dev_enabled(dev) && !(dev->flags & ATA_DFLAG_SUSPENDED); 950 } 951 952 /*