diff options
author | Tejun Heo <htejun@gmail.com> | 2007-05-14 14:28:15 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-05-16 01:18:30 -0400 |
commit | 6ddcd3b0201a7ad72294347636d2b4028ddbd95d (patch) | |
tree | ef2d28ea1775693f632705ebe71ad3e451cd69f1 /drivers | |
parent | fe30911b34098db58c21d0f936f6c3f17f32deb8 (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')
-rw-r--r-- | drivers/ata/libata-core.c | 33 |
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 | */ |
3724 | int ata_dev_revalidate(struct ata_device *dev, unsigned int readid_flags) | 3708 | int 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); |