diff options
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r-- | drivers/ata/libata-core.c | 74 |
1 files changed, 45 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; |