diff options
-rw-r--r-- | drivers/ata/libata-core.c | 28 | ||||
-rw-r--r-- | include/linux/ata.h | 2 |
2 files changed, 29 insertions, 1 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 6d0a946afe84..227399e48470 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -1649,13 +1649,13 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, | |||
1649 | struct ata_taskfile tf; | 1649 | struct ata_taskfile tf; |
1650 | unsigned int err_mask = 0; | 1650 | unsigned int err_mask = 0; |
1651 | const char *reason; | 1651 | const char *reason; |
1652 | int tried_spinup = 0; | ||
1652 | int rc; | 1653 | int rc; |
1653 | 1654 | ||
1654 | if (ata_msg_ctl(ap)) | 1655 | if (ata_msg_ctl(ap)) |
1655 | ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__); | 1656 | ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__); |
1656 | 1657 | ||
1657 | ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ | 1658 | ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */ |
1658 | |||
1659 | retry: | 1659 | retry: |
1660 | ata_tf_init(dev, &tf); | 1660 | ata_tf_init(dev, &tf); |
1661 | 1661 | ||
@@ -1712,6 +1712,32 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, | |||
1712 | goto err_out; | 1712 | goto err_out; |
1713 | } | 1713 | } |
1714 | 1714 | ||
1715 | if (!tried_spinup && (id[2] == 0x37c8 || id[2] == 0x738c)) { | ||
1716 | tried_spinup = 1; | ||
1717 | /* | ||
1718 | * Drive powered-up in standby mode, and requires a specific | ||
1719 | * SET_FEATURES spin-up subcommand before it will accept | ||
1720 | * anything other than the original IDENTIFY command. | ||
1721 | */ | ||
1722 | ata_tf_init(dev, &tf); | ||
1723 | tf.command = ATA_CMD_SET_FEATURES; | ||
1724 | tf.feature = SETFEATURES_SPINUP; | ||
1725 | tf.protocol = ATA_PROT_NODATA; | ||
1726 | tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; | ||
1727 | err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0); | ||
1728 | if (err_mask) { | ||
1729 | rc = -EIO; | ||
1730 | reason = "SPINUP failed"; | ||
1731 | goto err_out; | ||
1732 | } | ||
1733 | /* | ||
1734 | * If the drive initially returned incomplete IDENTIFY info, | ||
1735 | * we now must reissue the IDENTIFY command. | ||
1736 | */ | ||
1737 | if (id[2] == 0x37c8) | ||
1738 | goto retry; | ||
1739 | } | ||
1740 | |||
1715 | if ((flags & ATA_READID_POSTRESET) && class == ATA_DEV_ATA) { | 1741 | if ((flags & ATA_READID_POSTRESET) && class == ATA_DEV_ATA) { |
1716 | /* | 1742 | /* |
1717 | * The exact sequence expected by certain pre-ATA4 drives is: | 1743 | * The exact sequence expected by certain pre-ATA4 drives is: |
diff --git a/include/linux/ata.h b/include/linux/ata.h index f4dc8dfeadc2..edb31bfff68f 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h | |||
@@ -202,6 +202,8 @@ enum { | |||
202 | SETFEATURES_WC_ON = 0x02, /* Enable write cache */ | 202 | SETFEATURES_WC_ON = 0x02, /* Enable write cache */ |
203 | SETFEATURES_WC_OFF = 0x82, /* Disable write cache */ | 203 | SETFEATURES_WC_OFF = 0x82, /* Disable write cache */ |
204 | 204 | ||
205 | SETFEATURES_SPINUP = 0x07, /* Spin-up drive */ | ||
206 | |||
205 | /* ATAPI stuff */ | 207 | /* ATAPI stuff */ |
206 | ATAPI_PKT_DMA = (1 << 0), | 208 | ATAPI_PKT_DMA = (1 << 0), |
207 | ATAPI_DMADIR = (1 << 2), /* ATAPI data dir: | 209 | ATAPI_DMADIR = (1 << 2), /* ATAPI data dir: |