aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-05-14 14:28:15 -0400
committerJeff Garzik <jeff@garzik.org>2007-05-16 01:18:30 -0400
commit6ddcd3b0201a7ad72294347636d2b4028ddbd95d (patch)
treeef2d28ea1775693f632705ebe71ad3e451cd69f1 /drivers/ata
parentfe30911b34098db58c21d0f936f6c3f17f32deb8 (diff)
libata: during revalidation, check n_sectors after device is configured
Device might be resized during ata_dev_configure() due to HPA or (later) ACPI _GTF. Currently it's worked around by caching n_sectors before turning off HPA. The cached original size is overwritten if the device is reconfigured without being hardreset - which always happens after configuring trasnfer mode. If the device gets hardreset for some reason after that, revalidation fails with -ENODEV. This patch makes size checking more robust by moving n_sectors check from ata_dev_reread_id() to ata_dev_revalidate() after the device is fully configured. No matter what happens during configuration, a device must have the same n_sectors after fully configured to be treated as the same device. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/libata-core.c33
1 files changed, 15 insertions, 18 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 6f266c8179ec..d5939e659cbb 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1919,7 +1919,6 @@ int ata_dev_configure(struct ata_device *dev)
1919 snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id)); 1919 snprintf(revbuf, 7, "ATA-%d", ata_id_major_version(id));
1920 1920
1921 dev->n_sectors = ata_id_n_sectors(id); 1921 dev->n_sectors = ata_id_n_sectors(id);
1922 dev->n_sectors_boot = dev->n_sectors;
1923 1922
1924 /* SCSI only uses 4-char revisions, dump full 8 chars from ATA */ 1923 /* SCSI only uses 4-char revisions, dump full 8 chars from ATA */
1925 ata_id_c_string(dev->id, fwrevbuf, ATA_ID_FW_REV, 1924 ata_id_c_string(dev->id, fwrevbuf, ATA_ID_FW_REV,
@@ -3632,7 +3631,6 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
3632 const u16 *old_id = dev->id; 3631 const u16 *old_id = dev->id;
3633 unsigned char model[2][ATA_ID_PROD_LEN + 1]; 3632 unsigned char model[2][ATA_ID_PROD_LEN + 1];
3634 unsigned char serial[2][ATA_ID_SERNO_LEN + 1]; 3633 unsigned char serial[2][ATA_ID_SERNO_LEN + 1];
3635 u64 new_n_sectors;
3636 3634
3637 if (dev->class != new_class) { 3635 if (dev->class != new_class) {
3638 ata_dev_printk(dev, KERN_INFO, "class mismatch %d != %d\n", 3636 ata_dev_printk(dev, KERN_INFO, "class mismatch %d != %d\n",
@@ -3644,7 +3642,6 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
3644 ata_id_c_string(new_id, model[1], ATA_ID_PROD, sizeof(model[1])); 3642 ata_id_c_string(new_id, model[1], ATA_ID_PROD, sizeof(model[1]));
3645 ata_id_c_string(old_id, serial[0], ATA_ID_SERNO, sizeof(serial[0])); 3643 ata_id_c_string(old_id, serial[0], ATA_ID_SERNO, sizeof(serial[0]));
3646 ata_id_c_string(new_id, serial[1], ATA_ID_SERNO, sizeof(serial[1])); 3644 ata_id_c_string(new_id, serial[1], ATA_ID_SERNO, sizeof(serial[1]));
3647 new_n_sectors = ata_id_n_sectors(new_id);
3648 3645
3649 if (strcmp(model[0], model[1])) { 3646 if (strcmp(model[0], model[1])) {
3650 ata_dev_printk(dev, KERN_INFO, "model number mismatch " 3647 ata_dev_printk(dev, KERN_INFO, "model number mismatch "
@@ -3658,19 +3655,6 @@ static int ata_dev_same_device(struct ata_device *dev, unsigned int new_class,
3658 return 0; 3655 return 0;
3659 } 3656 }
3660 3657
3661 if (dev->class == ATA_DEV_ATA && dev->n_sectors != new_n_sectors) {
3662 ata_dev_printk(dev, KERN_INFO, "n_sectors mismatch "
3663 "%llu != %llu\n",
3664 (unsigned long long)dev->n_sectors,
3665 (unsigned long long)new_n_sectors);
3666 /* Are we the boot time size - if so we appear to be the
3667 same disk at this point and our HPA got reapplied */
3668 if (ata_ignore_hpa && dev->n_sectors_boot == new_n_sectors
3669 && ata_id_hpa_enabled(new_id))
3670 return 1;
3671 return 0;
3672 }
3673
3674 return 1; 3658 return 1;
3675} 3659}
3676 3660
@@ -3723,6 +3707,7 @@ int ata_dev_reread_id(struct ata_device *dev, unsigned int readid_flags)
3723 */ 3707 */
3724int ata_dev_revalidate(struct ata_device *dev, unsigned int readid_flags) 3708int ata_dev_revalidate(struct ata_device *dev, unsigned int readid_flags)
3725{ 3709{
3710 u64 n_sectors = dev->n_sectors;
3726 int rc; 3711 int rc;
3727 3712
3728 if (!ata_dev_enabled(dev)) 3713 if (!ata_dev_enabled(dev))
@@ -3735,8 +3720,20 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int readid_flags)
3735 3720
3736 /* configure device according to the new ID */ 3721 /* configure device according to the new ID */
3737 rc = ata_dev_configure(dev); 3722 rc = ata_dev_configure(dev);
3738 if (rc == 0) 3723 if (rc)
3739 return 0; 3724 goto fail;
3725
3726 /* verify n_sectors hasn't changed */
3727 if (dev->class == ATA_DEV_ATA && dev->n_sectors != n_sectors) {
3728 ata_dev_printk(dev, KERN_INFO, "n_sectors mismatch "
3729 "%llu != %llu\n",
3730 (unsigned long long)n_sectors,
3731 (unsigned long long)dev->n_sectors);
3732 rc = -ENODEV;
3733 goto fail;
3734 }
3735
3736 return 0;
3740 3737
3741 fail: 3738 fail:
3742 ata_dev_printk(dev, KERN_ERR, "revalidation failed (errno=%d)\n", rc); 3739 ata_dev_printk(dev, KERN_ERR, "revalidation failed (errno=%d)\n", rc);