summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/libata-core.c30
-rw-r--r--include/linux/libata.h1
2 files changed, 24 insertions, 7 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 2c6aedaef718..8ac98ff16d7d 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1515,6 +1515,7 @@ static int ata_hpa_resize(struct ata_device *dev)
return rc;
}
+ dev->n_native_sectors = native_sectors;
/* nothing to do? */
if (native_sectors <= sectors || !ata_ignore_hpa) {
@@ -4099,6 +4100,7 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
unsigned int readid_flags)
{
u64 n_sectors = dev->n_sectors;
+ u64 n_native_sectors = dev->n_native_sectors;
int rc;
if (!ata_dev_enabled(dev))
@@ -4128,16 +4130,30 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
/* verify n_sectors hasn't changed */
if (dev->class == ATA_DEV_ATA && n_sectors &&
dev->n_sectors != n_sectors) {
- ata_dev_printk(dev, KERN_INFO, "n_sectors mismatch "
+ ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch "
"%llu != %llu\n",
(unsigned long long)n_sectors,
(unsigned long long)dev->n_sectors);
-
- /* restore original n_sectors */
- dev->n_sectors = n_sectors;
-
- rc = -ENODEV;
- goto fail;
+ /*
+ * Something could have caused HPA to be unlocked
+ * involuntarily. If n_native_sectors hasn't changed
+ * and the new size matches it, keep the device.
+ */
+ if (dev->n_native_sectors == n_native_sectors &&
+ dev->n_sectors > n_sectors &&
+ dev->n_sectors == n_native_sectors) {
+ ata_dev_printk(dev, KERN_WARNING,
+ "new n_sectors matches native, probably "
+ "late HPA unlock, continuing\n");
+ /* keep using the old n_sectors */
+ dev->n_sectors = n_sectors;
+ } else {
+ /* restore original n_[native]_sectors and fail */
+ dev->n_native_sectors = n_native_sectors;
+ dev->n_sectors = n_sectors;
+ rc = -ENODEV;
+ goto fail;
+ }
}
return 0;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 79b6d7fd4ac2..e5b6e33c6571 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -589,6 +589,7 @@ struct ata_device {
#endif
/* n_sector is CLEAR_BEGIN, read comment above CLEAR_BEGIN */
u64 n_sectors; /* size of device, if ATA */
+ u64 n_native_sectors; /* native size, if ATA */
unsigned int class; /* ATA_DEV_xxx */
unsigned long unpark_deadline;