aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/libata-core.c74
-rw-r--r--include/linux/libata.h1
2 files changed, 46 insertions, 29 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 2ab34dc97f6f..49cffb6094a3 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1494,6 +1494,7 @@ static int ata_hpa_resize(struct ata_device *dev)
1494{ 1494{
1495 struct ata_eh_context *ehc = &dev->link->eh_context; 1495 struct ata_eh_context *ehc = &dev->link->eh_context;
1496 int print_info = ehc->i.flags & ATA_EHI_PRINTINFO; 1496 int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
1497 bool unlock_hpa = ata_ignore_hpa || dev->flags & ATA_DFLAG_UNLOCK_HPA;
1497 u64 sectors = ata_id_n_sectors(dev->id); 1498 u64 sectors = ata_id_n_sectors(dev->id);
1498 u64 native_sectors; 1499 u64 native_sectors;
1499 int rc; 1500 int rc;
@@ -1510,7 +1511,7 @@ static int ata_hpa_resize(struct ata_device *dev)
1510 /* If device aborted the command or HPA isn't going to 1511 /* If device aborted the command or HPA isn't going to
1511 * be unlocked, skip HPA resizing. 1512 * be unlocked, skip HPA resizing.
1512 */ 1513 */
1513 if (rc == -EACCES || !ata_ignore_hpa) { 1514 if (rc == -EACCES || !unlock_hpa) {
1514 ata_dev_printk(dev, KERN_WARNING, "HPA support seems " 1515 ata_dev_printk(dev, KERN_WARNING, "HPA support seems "
1515 "broken, skipping HPA handling\n"); 1516 "broken, skipping HPA handling\n");
1516 dev->horkage |= ATA_HORKAGE_BROKEN_HPA; 1517 dev->horkage |= ATA_HORKAGE_BROKEN_HPA;
@@ -1525,7 +1526,7 @@ static int ata_hpa_resize(struct ata_device *dev)
1525 dev->n_native_sectors = native_sectors; 1526 dev->n_native_sectors = native_sectors;
1526 1527
1527 /* nothing to do? */ 1528 /* nothing to do? */
1528 if (native_sectors <= sectors || !ata_ignore_hpa) { 1529 if (native_sectors <= sectors || !unlock_hpa) {
1529 if (!print_info || native_sectors == sectors) 1530 if (!print_info || native_sectors == sectors)
1530 return 0; 1531 return 0;
1531 1532
@@ -4186,36 +4187,51 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
4186 goto fail; 4187 goto fail;
4187 4188
4188 /* verify n_sectors hasn't changed */ 4189 /* verify n_sectors hasn't changed */
4189 if (dev->class == ATA_DEV_ATA && n_sectors && 4190 if (dev->class != ATA_DEV_ATA || !n_sectors ||
4190 dev->n_sectors != n_sectors) { 4191 dev->n_sectors == n_sectors)
4191 ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch " 4192 return 0;
4192 "%llu != %llu\n", 4193
4193 (unsigned long long)n_sectors, 4194 /* n_sectors has changed */
4194 (unsigned long long)dev->n_sectors); 4195 ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch %llu != %llu\n",
4195 /* 4196 (unsigned long long)n_sectors,
4196 * Something could have caused HPA to be unlocked 4197 (unsigned long long)dev->n_sectors);
4197 * involuntarily. If n_native_sectors hasn't changed 4198
4198 * and the new size matches it, keep the device. 4199 /*
4199 */ 4200 * Something could have caused HPA to be unlocked
4200 if (dev->n_native_sectors == n_native_sectors && 4201 * involuntarily. If n_native_sectors hasn't changed and the
4201 dev->n_sectors > n_sectors && 4202 * new size matches it, keep the device.
4202 dev->n_sectors == n_native_sectors) { 4203 */
4203 ata_dev_printk(dev, KERN_WARNING, 4204 if (dev->n_native_sectors == n_native_sectors &&
4204 "new n_sectors matches native, probably " 4205 dev->n_sectors > n_sectors && dev->n_sectors == n_native_sectors) {
4205 "late HPA unlock, continuing\n"); 4206 ata_dev_printk(dev, KERN_WARNING,
4206 /* keep using the old n_sectors */ 4207 "new n_sectors matches native, probably "
4207 dev->n_sectors = n_sectors; 4208 "late HPA unlock, continuing\n");
4208 } else { 4209 /* keep using the old n_sectors */
4209 /* restore original n_[native]_sectors and fail */ 4210 dev->n_sectors = n_sectors;
4210 dev->n_native_sectors = n_native_sectors; 4211 return 0;
4211 dev->n_sectors = n_sectors;
4212 rc = -ENODEV;
4213 goto fail;
4214 }
4215 } 4212 }
4216 4213
4217 return 0; 4214 /*
4215 * Some BIOSes boot w/o HPA but resume w/ HPA locked. Try
4216 * unlocking HPA in those cases.
4217 *
4218 * https://bugzilla.kernel.org/show_bug.cgi?id=15396
4219 */
4220 if (dev->n_native_sectors == n_native_sectors &&
4221 dev->n_sectors < n_sectors && n_sectors == n_native_sectors &&
4222 !(dev->horkage & ATA_HORKAGE_BROKEN_HPA)) {
4223 ata_dev_printk(dev, KERN_WARNING,
4224 "old n_sectors matches native, probably "
4225 "late HPA lock, will try to unlock HPA\n");
4226 /* try unlocking HPA */
4227 dev->flags |= ATA_DFLAG_UNLOCK_HPA;
4228 rc = -EIO;
4229 } else
4230 rc = -ENODEV;
4218 4231
4232 /* restore original n_[native_]sectors and fail */
4233 dev->n_native_sectors = n_native_sectors;
4234 dev->n_sectors = n_sectors;
4219 fail: 4235 fail:
4220 ata_dev_printk(dev, KERN_ERR, "revalidation failed (errno=%d)\n", rc); 4236 ata_dev_printk(dev, KERN_ERR, "revalidation failed (errno=%d)\n", rc);
4221 return rc; 4237 return rc;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index f8ea71e6d0e2..b2f2003b92e5 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -146,6 +146,7 @@ enum {
146 ATA_DFLAG_SLEEPING = (1 << 15), /* device is sleeping */ 146 ATA_DFLAG_SLEEPING = (1 << 15), /* device is sleeping */
147 ATA_DFLAG_DUBIOUS_XFER = (1 << 16), /* data transfer not verified */ 147 ATA_DFLAG_DUBIOUS_XFER = (1 << 16), /* data transfer not verified */
148 ATA_DFLAG_NO_UNLOAD = (1 << 17), /* device doesn't support unload */ 148 ATA_DFLAG_NO_UNLOAD = (1 << 17), /* device doesn't support unload */
149 ATA_DFLAG_UNLOCK_HPA = (1 << 18), /* unlock HPA */
149 ATA_DFLAG_INIT_MASK = (1 << 24) - 1, 150 ATA_DFLAG_INIT_MASK = (1 << 24) - 1,
150 151
151 ATA_DFLAG_DETACH = (1 << 24), 152 ATA_DFLAG_DETACH = (1 << 24),