diff options
| -rw-r--r-- | drivers/ata/libata-eh.c | 66 |
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 | ||
