Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 189540
b: refs/heads/master
c: 445d211
h: refs/heads/master
v: v3
  • Loading branch information
Tejun Heo authored and Jeff Garzik committed Apr 6, 2010
1 parent bd3cfb6 commit 7b0cf98
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 30 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 68b0ddb289220b6d4d865be128939663be34959d
refs/heads/master: 445d211b0da4e9a6e6d576edff85085c2aaf53df
74 changes: 45 additions & 29 deletions trunk/drivers/ata/libata-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1494,6 +1494,7 @@ static int ata_hpa_resize(struct ata_device *dev)
{
struct ata_eh_context *ehc = &dev->link->eh_context;
int print_info = ehc->i.flags & ATA_EHI_PRINTINFO;
bool unlock_hpa = ata_ignore_hpa || dev->flags & ATA_DFLAG_UNLOCK_HPA;
u64 sectors = ata_id_n_sectors(dev->id);
u64 native_sectors;
int rc;
Expand All @@ -1510,7 +1511,7 @@ static int ata_hpa_resize(struct ata_device *dev)
/* If device aborted the command or HPA isn't going to
* be unlocked, skip HPA resizing.
*/
if (rc == -EACCES || !ata_ignore_hpa) {
if (rc == -EACCES || !unlock_hpa) {
ata_dev_printk(dev, KERN_WARNING, "HPA support seems "
"broken, skipping HPA handling\n");
dev->horkage |= ATA_HORKAGE_BROKEN_HPA;
Expand All @@ -1525,7 +1526,7 @@ static int ata_hpa_resize(struct ata_device *dev)
dev->n_native_sectors = native_sectors;

/* nothing to do? */
if (native_sectors <= sectors || !ata_ignore_hpa) {
if (native_sectors <= sectors || !unlock_hpa) {
if (!print_info || native_sectors == sectors)
return 0;

Expand Down Expand Up @@ -4186,36 +4187,51 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
goto fail;

/* verify n_sectors hasn't changed */
if (dev->class == ATA_DEV_ATA && n_sectors &&
dev->n_sectors != n_sectors) {
ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch "
"%llu != %llu\n",
(unsigned long long)n_sectors,
(unsigned long long)dev->n_sectors);
/*
* 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;
}
if (dev->class != ATA_DEV_ATA || !n_sectors ||
dev->n_sectors == n_sectors)
return 0;

/* n_sectors has changed */
ata_dev_printk(dev, KERN_WARNING, "n_sectors mismatch %llu != %llu\n",
(unsigned long long)n_sectors,
(unsigned long long)dev->n_sectors);

/*
* 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;
return 0;
}

return 0;
/*
* Some BIOSes boot w/o HPA but resume w/ HPA locked. Try
* unlocking HPA in those cases.
*
* https://bugzilla.kernel.org/show_bug.cgi?id=15396
*/
if (dev->n_native_sectors == n_native_sectors &&
dev->n_sectors < n_sectors && n_sectors == n_native_sectors &&
!(dev->horkage & ATA_HORKAGE_BROKEN_HPA)) {
ata_dev_printk(dev, KERN_WARNING,
"old n_sectors matches native, probably "
"late HPA lock, will try to unlock HPA\n");
/* try unlocking HPA */
dev->flags |= ATA_DFLAG_UNLOCK_HPA;
rc = -EIO;
} else
rc = -ENODEV;

/* restore original n_[native_]sectors and fail */
dev->n_native_sectors = n_native_sectors;
dev->n_sectors = n_sectors;
fail:
ata_dev_printk(dev, KERN_ERR, "revalidation failed (errno=%d)\n", rc);
return rc;
Expand Down
1 change: 1 addition & 0 deletions trunk/include/linux/libata.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ enum {
ATA_DFLAG_SLEEPING = (1 << 15), /* device is sleeping */
ATA_DFLAG_DUBIOUS_XFER = (1 << 16), /* data transfer not verified */
ATA_DFLAG_NO_UNLOAD = (1 << 17), /* device doesn't support unload */
ATA_DFLAG_UNLOCK_HPA = (1 << 18), /* unlock HPA */
ATA_DFLAG_INIT_MASK = (1 << 24) - 1,

ATA_DFLAG_DETACH = (1 << 24),
Expand Down

0 comments on commit 7b0cf98

Please sign in to comment.