diff options
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r-- | drivers/ata/libata-core.c | 50 |
1 files changed, 41 insertions, 9 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 045a486a09ea..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) | |||
1515 | 1515 | ||
1516 | return rc; | 1516 | return rc; |
1517 | } | 1517 | } |
1518 | dev->n_native_sectors = native_sectors; | ||
1518 | 1519 | ||
1519 | /* nothing to do? */ | 1520 | /* nothing to do? */ |
1520 | if (native_sectors <= sectors || !ata_ignore_hpa) { | 1521 | if (native_sectors <= sectors || !ata_ignore_hpa) { |
@@ -3392,17 +3393,27 @@ int ata_down_xfermask_limit(struct ata_device *dev, unsigned int sel) | |||
3392 | 3393 | ||
3393 | static int ata_dev_set_mode(struct ata_device *dev) | 3394 | static int ata_dev_set_mode(struct ata_device *dev) |
3394 | { | 3395 | { |
3396 | struct ata_port *ap = dev->link->ap; | ||
3395 | struct ata_eh_context *ehc = &dev->link->eh_context; | 3397 | struct ata_eh_context *ehc = &dev->link->eh_context; |
3398 | const bool nosetxfer = dev->horkage & ATA_HORKAGE_NOSETXFER; | ||
3396 | const char *dev_err_whine = ""; | 3399 | const char *dev_err_whine = ""; |
3397 | int ign_dev_err = 0; | 3400 | int ign_dev_err = 0; |
3398 | unsigned int err_mask; | 3401 | unsigned int err_mask = 0; |
3399 | int rc; | 3402 | int rc; |
3400 | 3403 | ||
3401 | dev->flags &= ~ATA_DFLAG_PIO; | 3404 | dev->flags &= ~ATA_DFLAG_PIO; |
3402 | if (dev->xfer_shift == ATA_SHIFT_PIO) | 3405 | if (dev->xfer_shift == ATA_SHIFT_PIO) |
3403 | dev->flags |= ATA_DFLAG_PIO; | 3406 | dev->flags |= ATA_DFLAG_PIO; |
3404 | 3407 | ||
3405 | err_mask = ata_dev_set_xfermode(dev); | 3408 | if (nosetxfer && ap->flags & ATA_FLAG_SATA && ata_id_is_sata(dev->id)) |
3409 | dev_err_whine = " (SET_XFERMODE skipped)"; | ||
3410 | else { | ||
3411 | if (nosetxfer) | ||
3412 | ata_dev_printk(dev, KERN_WARNING, | ||
3413 | "NOSETXFER but PATA detected - can't " | ||
3414 | "skip SETXFER, might malfunction\n"); | ||
3415 | err_mask = ata_dev_set_xfermode(dev); | ||
3416 | } | ||
3406 | 3417 | ||
3407 | if (err_mask & ~AC_ERR_DEV) | 3418 | if (err_mask & ~AC_ERR_DEV) |
3408 | goto fail; | 3419 | goto fail; |
@@ -4089,6 +4100,7 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class, | |||
4089 | unsigned int readid_flags) | 4100 | unsigned int readid_flags) |
4090 | { | 4101 | { |
4091 | u64 n_sectors = dev->n_sectors; | 4102 | u64 n_sectors = dev->n_sectors; |
4103 | u64 n_native_sectors = dev->n_native_sectors; | ||
4092 | int rc; | 4104 | int rc; |
4093 | 4105 | ||
4094 | if (!ata_dev_enabled(dev)) | 4106 | if (!ata_dev_enabled(dev)) |
@@ -4118,16 +4130,30 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class, | |||
4118 | /* verify n_sectors hasn't changed */ | 4130 | /* verify n_sectors hasn't changed */ |
4119 | if (dev->class == ATA_DEV_ATA && n_sectors && | 4131 | if (dev->class == ATA_DEV_ATA && n_sectors && |
4120 | dev->n_sectors != n_sectors) { | 4132 | dev->n_sectors != n_sectors) { |
4121 | ata_dev_printk(dev, KERN_INFO, "n_sectors mismatch " | 4133 | ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch " |
4122 | "%llu != %llu\n", | 4134 | "%llu != %llu\n", |
4123 | (unsigned long long)n_sectors, | 4135 | (unsigned long long)n_sectors, |
4124 | (unsigned long long)dev->n_sectors); | 4136 | (unsigned long long)dev->n_sectors); |
4125 | 4137 | /* | |
4126 | /* restore original n_sectors */ | 4138 | * Something could have caused HPA to be unlocked |
4127 | dev->n_sectors = n_sectors; | 4139 | * involuntarily. If n_native_sectors hasn't changed |
4128 | 4140 | * and the new size matches it, keep the device. | |
4129 | rc = -ENODEV; | 4141 | */ |
4130 | goto fail; | 4142 | if (dev->n_native_sectors == n_native_sectors && |
4143 | dev->n_sectors > n_sectors && | ||
4144 | dev->n_sectors == n_native_sectors) { | ||
4145 | ata_dev_printk(dev, KERN_WARNING, | ||
4146 | "new n_sectors matches native, probably " | ||
4147 | "late HPA unlock, continuing\n"); | ||
4148 | /* keep using the old n_sectors */ | ||
4149 | dev->n_sectors = n_sectors; | ||
4150 | } else { | ||
4151 | /* restore original n_[native]_sectors and fail */ | ||
4152 | dev->n_native_sectors = n_native_sectors; | ||
4153 | dev->n_sectors = n_sectors; | ||
4154 | rc = -ENODEV; | ||
4155 | goto fail; | ||
4156 | } | ||
4131 | } | 4157 | } |
4132 | 4158 | ||
4133 | return 0; | 4159 | return 0; |
@@ -4297,6 +4323,12 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { | |||
4297 | /* Devices which aren't very happy with higher link speeds */ | 4323 | /* Devices which aren't very happy with higher link speeds */ |
4298 | { "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS, }, | 4324 | { "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS, }, |
4299 | 4325 | ||
4326 | /* | ||
4327 | * Devices which choke on SETXFER. Applies only if both the | ||
4328 | * device and controller are SATA. | ||
4329 | */ | ||
4330 | { "PIONEER DVD-RW DVRTD08", "1.00", ATA_HORKAGE_NOSETXFER }, | ||
4331 | |||
4300 | /* End Marker */ | 4332 | /* End Marker */ |
4301 | { } | 4333 | { } |
4302 | }; | 4334 | }; |