diff options
Diffstat (limited to 'drivers/ata/libata-eh.c')
-rw-r--r-- | drivers/ata/libata-eh.c | 96 |
1 files changed, 60 insertions, 36 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 7349c3dbf774..39f556c02992 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
@@ -982,26 +982,27 @@ static int ata_eh_read_log_10h(struct ata_device *dev, | |||
982 | * RETURNS: | 982 | * RETURNS: |
983 | * 0 on success, AC_ERR_* mask on failure | 983 | * 0 on success, AC_ERR_* mask on failure |
984 | */ | 984 | */ |
985 | static unsigned int atapi_eh_request_sense(struct ata_device *dev, | 985 | static unsigned int atapi_eh_request_sense(struct ata_queued_cmd *qc) |
986 | unsigned char *sense_buf) | ||
987 | { | 986 | { |
987 | struct ata_device *dev = qc->dev; | ||
988 | unsigned char *sense_buf = qc->scsicmd->sense_buffer; | ||
988 | struct ata_port *ap = dev->ap; | 989 | struct ata_port *ap = dev->ap; |
989 | struct ata_taskfile tf; | 990 | struct ata_taskfile tf; |
990 | u8 cdb[ATAPI_CDB_LEN]; | 991 | u8 cdb[ATAPI_CDB_LEN]; |
991 | 992 | ||
992 | DPRINTK("ATAPI request sense\n"); | 993 | DPRINTK("ATAPI request sense\n"); |
993 | 994 | ||
994 | ata_tf_init(dev, &tf); | ||
995 | |||
996 | /* FIXME: is this needed? */ | 995 | /* FIXME: is this needed? */ |
997 | memset(sense_buf, 0, SCSI_SENSE_BUFFERSIZE); | 996 | memset(sense_buf, 0, SCSI_SENSE_BUFFERSIZE); |
998 | 997 | ||
999 | /* XXX: why tf_read here? */ | 998 | /* initialize sense_buf with the error register, |
1000 | ap->ops->tf_read(ap, &tf); | 999 | * for the case where they are -not- overwritten |
1001 | 1000 | */ | |
1002 | /* fill these in, for the case where they are -not- overwritten */ | ||
1003 | sense_buf[0] = 0x70; | 1001 | sense_buf[0] = 0x70; |
1004 | sense_buf[2] = tf.feature >> 4; | 1002 | sense_buf[2] = qc->result_tf.feature >> 4; |
1003 | |||
1004 | /* some devices time out if garbage left in tf */ | ||
1005 | ata_tf_init(dev, &tf); | ||
1005 | 1006 | ||
1006 | memset(cdb, 0, ATAPI_CDB_LEN); | 1007 | memset(cdb, 0, ATAPI_CDB_LEN); |
1007 | cdb[0] = REQUEST_SENSE; | 1008 | cdb[0] = REQUEST_SENSE; |
@@ -1165,8 +1166,7 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc, | |||
1165 | 1166 | ||
1166 | case ATA_DEV_ATAPI: | 1167 | case ATA_DEV_ATAPI: |
1167 | if (!(qc->ap->pflags & ATA_PFLAG_FROZEN)) { | 1168 | if (!(qc->ap->pflags & ATA_PFLAG_FROZEN)) { |
1168 | tmp = atapi_eh_request_sense(qc->dev, | 1169 | tmp = atapi_eh_request_sense(qc); |
1169 | qc->scsicmd->sense_buffer); | ||
1170 | if (!tmp) { | 1170 | if (!tmp) { |
1171 | /* ATA_QCFLAG_SENSE_VALID is used to | 1171 | /* ATA_QCFLAG_SENSE_VALID is used to |
1172 | * tell atapi_qc_complete() that sense | 1172 | * tell atapi_qc_complete() that sense |
@@ -1625,8 +1625,14 @@ static int ata_eh_reset(struct ata_port *ap, int classify, | |||
1625 | rc = prereset(ap); | 1625 | rc = prereset(ap); |
1626 | if (rc) { | 1626 | if (rc) { |
1627 | if (rc == -ENOENT) { | 1627 | if (rc == -ENOENT) { |
1628 | ata_port_printk(ap, KERN_DEBUG, "port disabled. ignoring.\n"); | 1628 | ata_port_printk(ap, KERN_DEBUG, |
1629 | "port disabled. ignoring.\n"); | ||
1629 | ap->eh_context.i.action &= ~ATA_EH_RESET_MASK; | 1630 | ap->eh_context.i.action &= ~ATA_EH_RESET_MASK; |
1631 | |||
1632 | for (i = 0; i < ATA_MAX_DEVICES; i++) | ||
1633 | classes[i] = ATA_DEV_NONE; | ||
1634 | |||
1635 | rc = 0; | ||
1630 | } else | 1636 | } else |
1631 | ata_port_printk(ap, KERN_ERR, | 1637 | ata_port_printk(ap, KERN_ERR, |
1632 | "prereset failed (errno=%d)\n", rc); | 1638 | "prereset failed (errno=%d)\n", rc); |
@@ -1737,12 +1743,17 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, | |||
1737 | { | 1743 | { |
1738 | struct ata_eh_context *ehc = &ap->eh_context; | 1744 | struct ata_eh_context *ehc = &ap->eh_context; |
1739 | struct ata_device *dev; | 1745 | struct ata_device *dev; |
1746 | unsigned int new_mask = 0; | ||
1740 | unsigned long flags; | 1747 | unsigned long flags; |
1741 | int i, rc = 0; | 1748 | int i, rc = 0; |
1742 | 1749 | ||
1743 | DPRINTK("ENTER\n"); | 1750 | DPRINTK("ENTER\n"); |
1744 | 1751 | ||
1745 | 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--) { | ||
1746 | unsigned int action, readid_flags = 0; | 1757 | unsigned int action, readid_flags = 0; |
1747 | 1758 | ||
1748 | dev = &ap->device[i]; | 1759 | dev = &ap->device[i]; |
@@ -1754,13 +1765,13 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, | |||
1754 | if (action & ATA_EH_REVALIDATE && ata_dev_ready(dev)) { | 1765 | if (action & ATA_EH_REVALIDATE && ata_dev_ready(dev)) { |
1755 | if (ata_port_offline(ap)) { | 1766 | if (ata_port_offline(ap)) { |
1756 | rc = -EIO; | 1767 | rc = -EIO; |
1757 | break; | 1768 | goto err; |
1758 | } | 1769 | } |
1759 | 1770 | ||
1760 | ata_eh_about_to_do(ap, dev, ATA_EH_REVALIDATE); | 1771 | ata_eh_about_to_do(ap, dev, ATA_EH_REVALIDATE); |
1761 | rc = ata_dev_revalidate(dev, readid_flags); | 1772 | rc = ata_dev_revalidate(dev, readid_flags); |
1762 | if (rc) | 1773 | if (rc) |
1763 | break; | 1774 | goto err; |
1764 | 1775 | ||
1765 | ata_eh_done(ap, dev, ATA_EH_REVALIDATE); | 1776 | ata_eh_done(ap, dev, ATA_EH_REVALIDATE); |
1766 | 1777 | ||
@@ -1778,40 +1789,53 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, | |||
1778 | 1789 | ||
1779 | rc = ata_dev_read_id(dev, &dev->class, readid_flags, | 1790 | rc = ata_dev_read_id(dev, &dev->class, readid_flags, |
1780 | dev->id); | 1791 | dev->id); |
1781 | if (rc == 0) { | 1792 | switch (rc) { |
1782 | ehc->i.flags |= ATA_EHI_PRINTINFO; | 1793 | case 0: |
1783 | rc = ata_dev_configure(dev); | 1794 | new_mask |= 1 << i; |
1784 | ehc->i.flags &= ~ATA_EHI_PRINTINFO; | 1795 | break; |
1785 | } else if (rc == -ENOENT) { | 1796 | case -ENOENT: |
1786 | /* IDENTIFY was issued to non-existent | 1797 | /* IDENTIFY was issued to non-existent |
1787 | * device. No need to reset. Just | 1798 | * device. No need to reset. Just |
1788 | * thaw and kill the device. | 1799 | * thaw and kill the device. |
1789 | */ | 1800 | */ |
1790 | ata_eh_thaw_port(ap); | 1801 | ata_eh_thaw_port(ap); |
1791 | dev->class = ATA_DEV_UNKNOWN; | 1802 | dev->class = ATA_DEV_UNKNOWN; |
1792 | rc = 0; | ||
1793 | } | ||
1794 | |||
1795 | if (rc) { | ||
1796 | dev->class = ATA_DEV_UNKNOWN; | ||
1797 | break; | 1803 | break; |
1804 | default: | ||
1805 | dev->class = ATA_DEV_UNKNOWN; | ||
1806 | goto err; | ||
1798 | } | 1807 | } |
1808 | } | ||
1809 | } | ||
1799 | 1810 | ||
1800 | if (ata_dev_enabled(dev)) { | 1811 | /* Configure new devices forward such that user doesn't see |
1801 | spin_lock_irqsave(ap->lock, flags); | 1812 | * device detection messages backwards. |
1802 | ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG; | 1813 | */ |
1803 | spin_unlock_irqrestore(ap->lock, flags); | 1814 | for (i = 0; i < ATA_MAX_DEVICES; i++) { |
1815 | dev = &ap->device[i]; | ||
1804 | 1816 | ||
1805 | /* new device discovered, configure xfermode */ | 1817 | if (!(new_mask & (1 << i))) |
1806 | ehc->i.flags |= ATA_EHI_SETMODE; | 1818 | continue; |
1807 | } | 1819 | |
1808 | } | 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; | ||
1809 | } | 1832 | } |
1810 | 1833 | ||
1811 | if (rc) | 1834 | return 0; |
1812 | *r_failed_dev = dev; | ||
1813 | 1835 | ||
1814 | DPRINTK("EXIT\n"); | 1836 | err: |
1837 | *r_failed_dev = dev; | ||
1838 | DPRINTK("EXIT rc=%d\n", rc); | ||
1815 | return rc; | 1839 | return rc; |
1816 | } | 1840 | } |
1817 | 1841 | ||