diff options
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r-- | drivers/ata/libata-core.c | 78 |
1 files changed, 49 insertions, 29 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 4a28420efff2..49cffb6094a3 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -58,6 +58,7 @@ | |||
58 | #include <linux/io.h> | 58 | #include <linux/io.h> |
59 | #include <linux/async.h> | 59 | #include <linux/async.h> |
60 | #include <linux/log2.h> | 60 | #include <linux/log2.h> |
61 | #include <linux/slab.h> | ||
61 | #include <scsi/scsi.h> | 62 | #include <scsi/scsi.h> |
62 | #include <scsi/scsi_cmnd.h> | 63 | #include <scsi/scsi_cmnd.h> |
63 | #include <scsi/scsi_host.h> | 64 | #include <scsi/scsi_host.h> |
@@ -1493,6 +1494,7 @@ static int ata_hpa_resize(struct ata_device *dev) | |||
1493 | { | 1494 | { |
1494 | struct ata_eh_context *ehc = &dev->link->eh_context; | 1495 | struct ata_eh_context *ehc = &dev->link->eh_context; |
1495 | 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; | ||
1496 | u64 sectors = ata_id_n_sectors(dev->id); | 1498 | u64 sectors = ata_id_n_sectors(dev->id); |
1497 | u64 native_sectors; | 1499 | u64 native_sectors; |
1498 | int rc; | 1500 | int rc; |
@@ -1509,7 +1511,7 @@ static int ata_hpa_resize(struct ata_device *dev) | |||
1509 | /* If device aborted the command or HPA isn't going to | 1511 | /* If device aborted the command or HPA isn't going to |
1510 | * be unlocked, skip HPA resizing. | 1512 | * be unlocked, skip HPA resizing. |
1511 | */ | 1513 | */ |
1512 | if (rc == -EACCES || !ata_ignore_hpa) { | 1514 | if (rc == -EACCES || !unlock_hpa) { |
1513 | ata_dev_printk(dev, KERN_WARNING, "HPA support seems " | 1515 | ata_dev_printk(dev, KERN_WARNING, "HPA support seems " |
1514 | "broken, skipping HPA handling\n"); | 1516 | "broken, skipping HPA handling\n"); |
1515 | dev->horkage |= ATA_HORKAGE_BROKEN_HPA; | 1517 | dev->horkage |= ATA_HORKAGE_BROKEN_HPA; |
@@ -1524,7 +1526,7 @@ static int ata_hpa_resize(struct ata_device *dev) | |||
1524 | dev->n_native_sectors = native_sectors; | 1526 | dev->n_native_sectors = native_sectors; |
1525 | 1527 | ||
1526 | /* nothing to do? */ | 1528 | /* nothing to do? */ |
1527 | if (native_sectors <= sectors || !ata_ignore_hpa) { | 1529 | if (native_sectors <= sectors || !unlock_hpa) { |
1528 | if (!print_info || native_sectors == sectors) | 1530 | if (!print_info || native_sectors == sectors) |
1529 | return 0; | 1531 | return 0; |
1530 | 1532 | ||
@@ -4185,36 +4187,51 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class, | |||
4185 | goto fail; | 4187 | goto fail; |
4186 | 4188 | ||
4187 | /* verify n_sectors hasn't changed */ | 4189 | /* verify n_sectors hasn't changed */ |
4188 | if (dev->class == ATA_DEV_ATA && n_sectors && | 4190 | if (dev->class != ATA_DEV_ATA || !n_sectors || |
4189 | dev->n_sectors != n_sectors) { | 4191 | dev->n_sectors == n_sectors) |
4190 | ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch " | 4192 | return 0; |
4191 | "%llu != %llu\n", | 4193 | |
4192 | (unsigned long long)n_sectors, | 4194 | /* n_sectors has changed */ |
4193 | (unsigned long long)dev->n_sectors); | 4195 | ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch %llu != %llu\n", |
4194 | /* | 4196 | (unsigned long long)n_sectors, |
4195 | * Something could have caused HPA to be unlocked | 4197 | (unsigned long long)dev->n_sectors); |
4196 | * involuntarily. If n_native_sectors hasn't changed | 4198 | |
4197 | * and the new size matches it, keep the device. | 4199 | /* |
4198 | */ | 4200 | * Something could have caused HPA to be unlocked |
4199 | if (dev->n_native_sectors == n_native_sectors && | 4201 | * involuntarily. If n_native_sectors hasn't changed and the |
4200 | dev->n_sectors > n_sectors && | 4202 | * new size matches it, keep the device. |
4201 | dev->n_sectors == n_native_sectors) { | 4203 | */ |
4202 | ata_dev_printk(dev, KERN_WARNING, | 4204 | if (dev->n_native_sectors == n_native_sectors && |
4203 | "new n_sectors matches native, probably " | 4205 | dev->n_sectors > n_sectors && dev->n_sectors == n_native_sectors) { |
4204 | "late HPA unlock, continuing\n"); | 4206 | ata_dev_printk(dev, KERN_WARNING, |
4205 | /* keep using the old n_sectors */ | 4207 | "new n_sectors matches native, probably " |
4206 | dev->n_sectors = n_sectors; | 4208 | "late HPA unlock, continuing\n"); |
4207 | } else { | 4209 | /* keep using the old n_sectors */ |
4208 | /* restore original n_[native]_sectors and fail */ | 4210 | dev->n_sectors = n_sectors; |
4209 | dev->n_native_sectors = n_native_sectors; | 4211 | return 0; |
4210 | dev->n_sectors = n_sectors; | ||
4211 | rc = -ENODEV; | ||
4212 | goto fail; | ||
4213 | } | ||
4214 | } | 4212 | } |
4215 | 4213 | ||
4216 | 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; | ||
4217 | 4231 | ||
4232 | /* restore original n_[native_]sectors and fail */ | ||
4233 | dev->n_native_sectors = n_native_sectors; | ||
4234 | dev->n_sectors = n_sectors; | ||
4218 | fail: | 4235 | fail: |
4219 | 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); |
4220 | return rc; | 4237 | return rc; |
@@ -4353,6 +4370,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { | |||
4353 | { "HTS541080G9SA00", "MB4OC60D", ATA_HORKAGE_NONCQ, }, | 4370 | { "HTS541080G9SA00", "MB4OC60D", ATA_HORKAGE_NONCQ, }, |
4354 | { "HTS541010G9SA00", "MBZOC60D", ATA_HORKAGE_NONCQ, }, | 4371 | { "HTS541010G9SA00", "MBZOC60D", ATA_HORKAGE_NONCQ, }, |
4355 | 4372 | ||
4373 | /* https://bugzilla.kernel.org/show_bug.cgi?id=15573 */ | ||
4374 | { "C300-CTFDDAC128MAG", "0001", ATA_HORKAGE_NONCQ, }, | ||
4375 | |||
4356 | /* devices which puke on READ_NATIVE_MAX */ | 4376 | /* devices which puke on READ_NATIVE_MAX */ |
4357 | { "HDS724040KLSA80", "KFAOA20N", ATA_HORKAGE_BROKEN_HPA, }, | 4377 | { "HDS724040KLSA80", "KFAOA20N", ATA_HORKAGE_BROKEN_HPA, }, |
4358 | { "WDC WD3200JD-00KLB0", "WD-WCAMR1130137", ATA_HORKAGE_BROKEN_HPA }, | 4378 | { "WDC WD3200JD-00KLB0", "WD-WCAMR1130137", ATA_HORKAGE_BROKEN_HPA }, |