aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-eh.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-03-22 09:24:19 -0400
committerJeff Garzik <jeff@garzik.org>2007-03-28 02:04:27 -0400
commit8c3c52a8f00536ce55dafa055b4a211f878f3901 (patch)
treec44fbfd5928ecd6329c3054fb88f04494d3508ef /drivers/ata/libata-eh.c
parent55a61604cd1354e1783364e1c901034f2f474b7d (diff)
libata: IDENTIFY backwards for drive side cable detection
For drive side cable detection to work correctly, drives need to be identified backwards such that the slave device releases PDIAG- before the mater drive tries to detect cable type. ata_bus_probe() was fixed by commit f31f0cc2f0b7527072d94d02da332d9bb8d7d94c but the new EH path wasn't fixed. This patch makes new EH path do IDENTIFY backwards. ata_dev_configure() for new devices are still performed master first. This is to keep the detection messages in forward order. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/libata-eh.c')
-rw-r--r--drivers/ata/libata-eh.c66
1 files changed, 42 insertions, 24 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 361953a50203..c89664a77a9c 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1743,12 +1743,17 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
1743{ 1743{
1744 struct ata_eh_context *ehc = &ap->eh_context; 1744 struct ata_eh_context *ehc = &ap->eh_context;
1745 struct ata_device *dev; 1745 struct ata_device *dev;
1746 unsigned int new_mask = 0;
1746 unsigned long flags; 1747 unsigned long flags;
1747 int i, rc = 0; 1748 int i, rc = 0;
1748 1749
1749 DPRINTK("ENTER\n"); 1750 DPRINTK("ENTER\n");
1750 1751
1751 for (i = 0; i < ATA_MAX_DEVICES; i++) { 1752 /* For PATA drive side cable detection to work, IDENTIFY must
1753 * be done backwards such that PDIAG- is released by the slave
1754 * device before the master device is identified.
1755 */
1756 for (i = ATA_MAX_DEVICES - 1; i >= 0; i--) {
1752 unsigned int action, readid_flags = 0; 1757 unsigned int action, readid_flags = 0;
1753 1758
1754 dev = &ap->device[i]; 1759 dev = &ap->device[i];
@@ -1760,13 +1765,13 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
1760 if (action & ATA_EH_REVALIDATE && ata_dev_ready(dev)) { 1765 if (action & ATA_EH_REVALIDATE && ata_dev_ready(dev)) {
1761 if (ata_port_offline(ap)) { 1766 if (ata_port_offline(ap)) {
1762 rc = -EIO; 1767 rc = -EIO;
1763 break; 1768 goto err;
1764 } 1769 }
1765 1770
1766 ata_eh_about_to_do(ap, dev, ATA_EH_REVALIDATE); 1771 ata_eh_about_to_do(ap, dev, ATA_EH_REVALIDATE);
1767 rc = ata_dev_revalidate(dev, readid_flags); 1772 rc = ata_dev_revalidate(dev, readid_flags);
1768 if (rc) 1773 if (rc)
1769 break; 1774 goto err;
1770 1775
1771 ata_eh_done(ap, dev, ATA_EH_REVALIDATE); 1776 ata_eh_done(ap, dev, ATA_EH_REVALIDATE);
1772 1777
@@ -1784,40 +1789,53 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
1784 1789
1785 rc = ata_dev_read_id(dev, &dev->class, readid_flags, 1790 rc = ata_dev_read_id(dev, &dev->class, readid_flags,
1786 dev->id); 1791 dev->id);
1787 if (rc == 0) { 1792 switch (rc) {
1788 ehc->i.flags |= ATA_EHI_PRINTINFO; 1793 case 0:
1789 rc = ata_dev_configure(dev); 1794 new_mask |= 1 << i;
1790 ehc->i.flags &= ~ATA_EHI_PRINTINFO; 1795 break;
1791 } else if (rc == -ENOENT) { 1796 case -ENOENT:
1792 /* IDENTIFY was issued to non-existent 1797 /* IDENTIFY was issued to non-existent
1793 * device. No need to reset. Just 1798 * device. No need to reset. Just
1794 * thaw and kill the device. 1799 * thaw and kill the device.
1795 */ 1800 */
1796 ata_eh_thaw_port(ap); 1801 ata_eh_thaw_port(ap);
1797 dev->class = ATA_DEV_UNKNOWN; 1802 dev->class = ATA_DEV_UNKNOWN;
1798 rc = 0;
1799 }
1800
1801 if (rc) {
1802 dev->class = ATA_DEV_UNKNOWN;
1803 break; 1803 break;
1804 default:
1805 dev->class = ATA_DEV_UNKNOWN;
1806 goto err;
1804 } 1807 }
1808 }
1809 }
1805 1810
1806 if (ata_dev_enabled(dev)) { 1811 /* Configure new devices forward such that user doesn't see
1807 spin_lock_irqsave(ap->lock, flags); 1812 * device detection messages backwards.
1808 ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG; 1813 */
1809 spin_unlock_irqrestore(ap->lock, flags); 1814 for (i = 0; i < ATA_MAX_DEVICES; i++) {
1815 dev = &ap->device[i];
1810 1816
1811 /* new device discovered, configure xfermode */ 1817 if (!(new_mask & (1 << i)))
1812 ehc->i.flags |= ATA_EHI_SETMODE; 1818 continue;
1813 } 1819
1814 } 1820 ehc->i.flags |= ATA_EHI_PRINTINFO;
1821 rc = ata_dev_configure(dev);
1822 ehc->i.flags &= ~ATA_EHI_PRINTINFO;
1823 if (rc)
1824 goto err;
1825
1826 spin_lock_irqsave(ap->lock, flags);
1827 ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
1828 spin_unlock_irqrestore(ap->lock, flags);
1829
1830 /* new device discovered, configure xfermode */
1831 ehc->i.flags |= ATA_EHI_SETMODE;
1815 } 1832 }
1816 1833
1817 if (rc) 1834 return 0;
1818 *r_failed_dev = dev;
1819 1835
1820 DPRINTK("EXIT\n"); 1836 err:
1837 *r_failed_dev = dev;
1838 DPRINTK("EXIT rc=%d\n", rc);
1821 return rc; 1839 return rc;
1822} 1840}
1823 1841