diff options
| author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2009-06-07 07:52:52 -0400 |
|---|---|---|
| committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2009-06-07 07:52:52 -0400 |
| commit | e957b60d1583022a0f7c03267d37fcae2ddb78b1 (patch) | |
| tree | 5e9518eb38d427b9ac41c9b90b31b9b2453aebfc /drivers/ide/ide-disk.c | |
| parent | db429e9ec0f9dee2d8e50c154f04f29f880fc9d6 (diff) | |
ide-gd: implement block device ->set_capacity method (v2)
* Use ->probed_capacity to store native device capacity for ATA disks.
* Add ->set_capacity method to struct ide_disk_ops.
* Implement disk device ->set_capacity method for ATA disks.
* Implement block device ->set_capacity method.
v2:
* Check if LBA and HPA are supported in ide_disk_set_capacity().
* According to the spec the SET MAX ADDRESS command shall be
immediately preceded by a READ NATIVE MAX ADDRESS command.
* Add ide_disk_hpa_{get_native,set}_capacity() helpers.
Together with the previous patch adding ->set_capacity block device
method this allows automatic disabling of Host Protected Area (HPA)
if any partitions overlapping HPA are detected.
Cc: Robert Hancock <hancockrwd@gmail.com>
Cc: Frans Pop <elendil@planet.nl>
Cc: "Andries E. Brouwer" <Andries.Brouwer@cwi.nl>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Emphatically-Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/ide-disk.c')
| -rw-r--r-- | drivers/ide/ide-disk.c | 67 |
1 files changed, 56 insertions, 11 deletions
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index a9fbe2c31210..61a6d3546221 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
| @@ -302,14 +302,12 @@ static const struct drive_list_entry hpa_list[] = { | |||
| 302 | { NULL, NULL } | 302 | { NULL, NULL } |
| 303 | }; | 303 | }; |
| 304 | 304 | ||
| 305 | static void idedisk_check_hpa(ide_drive_t *drive) | 305 | static u64 ide_disk_hpa_get_native_capacity(ide_drive_t *drive, int lba48) |
| 306 | { | 306 | { |
| 307 | unsigned long long capacity, set_max; | 307 | u64 capacity, set_max; |
| 308 | int lba48 = ata_id_lba48_enabled(drive->id); | ||
| 309 | 308 | ||
| 310 | capacity = drive->capacity64; | 309 | capacity = drive->capacity64; |
| 311 | 310 | set_max = idedisk_read_native_max_address(drive, lba48); | |
| 312 | set_max = idedisk_read_native_max_address(drive, lba48); | ||
| 313 | 311 | ||
| 314 | if (ide_in_drive_list(drive->id, hpa_list)) { | 312 | if (ide_in_drive_list(drive->id, hpa_list)) { |
| 315 | /* | 313 | /* |
| @@ -320,9 +318,31 @@ static void idedisk_check_hpa(ide_drive_t *drive) | |||
| 320 | set_max--; | 318 | set_max--; |
| 321 | } | 319 | } |
| 322 | 320 | ||
| 321 | return set_max; | ||
| 322 | } | ||
| 323 | |||
| 324 | static u64 ide_disk_hpa_set_capacity(ide_drive_t *drive, u64 set_max, int lba48) | ||
| 325 | { | ||
| 326 | set_max = idedisk_set_max_address(drive, set_max, lba48); | ||
| 327 | if (set_max) | ||
| 328 | drive->capacity64 = set_max; | ||
| 329 | |||
| 330 | return set_max; | ||
| 331 | } | ||
| 332 | |||
| 333 | static void idedisk_check_hpa(ide_drive_t *drive) | ||
| 334 | { | ||
| 335 | u64 capacity, set_max; | ||
| 336 | int lba48 = ata_id_lba48_enabled(drive->id); | ||
| 337 | |||
| 338 | capacity = drive->capacity64; | ||
| 339 | set_max = ide_disk_hpa_get_native_capacity(drive, lba48); | ||
| 340 | |||
| 323 | if (set_max <= capacity) | 341 | if (set_max <= capacity) |
| 324 | return; | 342 | return; |
| 325 | 343 | ||
| 344 | drive->probed_capacity = set_max; | ||
| 345 | |||
| 326 | printk(KERN_INFO "%s: Host Protected Area detected.\n" | 346 | printk(KERN_INFO "%s: Host Protected Area detected.\n" |
| 327 | "\tcurrent capacity is %llu sectors (%llu MB)\n" | 347 | "\tcurrent capacity is %llu sectors (%llu MB)\n" |
| 328 | "\tnative capacity is %llu sectors (%llu MB)\n", | 348 | "\tnative capacity is %llu sectors (%llu MB)\n", |
| @@ -330,13 +350,10 @@ static void idedisk_check_hpa(ide_drive_t *drive) | |||
| 330 | capacity, sectors_to_MB(capacity), | 350 | capacity, sectors_to_MB(capacity), |
| 331 | set_max, sectors_to_MB(set_max)); | 351 | set_max, sectors_to_MB(set_max)); |
| 332 | 352 | ||
| 333 | set_max = idedisk_set_max_address(drive, set_max, lba48); | 353 | set_max = ide_disk_hpa_set_capacity(drive, set_max, lba48); |
| 334 | 354 | if (set_max) | |
| 335 | if (set_max) { | ||
| 336 | drive->capacity64 = set_max; | ||
| 337 | printk(KERN_INFO "%s: Host Protected Area disabled.\n", | 355 | printk(KERN_INFO "%s: Host Protected Area disabled.\n", |
| 338 | drive->name); | 356 | drive->name); |
| 339 | } | ||
| 340 | } | 357 | } |
| 341 | 358 | ||
| 342 | static int ide_disk_get_capacity(ide_drive_t *drive) | 359 | static int ide_disk_get_capacity(ide_drive_t *drive) |
| @@ -358,6 +375,8 @@ static int ide_disk_get_capacity(ide_drive_t *drive) | |||
| 358 | drive->capacity64 = drive->cyl * drive->head * drive->sect; | 375 | drive->capacity64 = drive->cyl * drive->head * drive->sect; |
| 359 | } | 376 | } |
| 360 | 377 | ||
| 378 | drive->probed_capacity = drive->capacity64; | ||
| 379 | |||
| 361 | if (lba) { | 380 | if (lba) { |
| 362 | drive->dev_flags |= IDE_DFLAG_LBA; | 381 | drive->dev_flags |= IDE_DFLAG_LBA; |
| 363 | 382 | ||
| @@ -376,7 +395,7 @@ static int ide_disk_get_capacity(ide_drive_t *drive) | |||
| 376 | "%llu sectors (%llu MB)\n", | 395 | "%llu sectors (%llu MB)\n", |
| 377 | drive->name, (unsigned long long)drive->capacity64, | 396 | drive->name, (unsigned long long)drive->capacity64, |
| 378 | sectors_to_MB(drive->capacity64)); | 397 | sectors_to_MB(drive->capacity64)); |
| 379 | drive->capacity64 = 1ULL << 28; | 398 | drive->probed_capacity = drive->capacity64 = 1ULL << 28; |
| 380 | } | 399 | } |
| 381 | 400 | ||
| 382 | if ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && | 401 | if ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && |
| @@ -392,6 +411,31 @@ static int ide_disk_get_capacity(ide_drive_t *drive) | |||
| 392 | return 0; | 411 | return 0; |
| 393 | } | 412 | } |
| 394 | 413 | ||
| 414 | static u64 ide_disk_set_capacity(ide_drive_t *drive, u64 capacity) | ||
| 415 | { | ||
| 416 | u64 set = min(capacity, drive->probed_capacity); | ||
| 417 | u16 *id = drive->id; | ||
| 418 | int lba48 = ata_id_lba48_enabled(id); | ||
| 419 | |||
| 420 | if ((drive->dev_flags & IDE_DFLAG_LBA) == 0 || | ||
| 421 | ata_id_hpa_enabled(id) == 0) | ||
| 422 | goto out; | ||
| 423 | |||
| 424 | /* | ||
| 425 | * according to the spec the SET MAX ADDRESS command shall be | ||
| 426 | * immediately preceded by a READ NATIVE MAX ADDRESS command | ||
| 427 | */ | ||
| 428 | capacity = ide_disk_hpa_get_native_capacity(drive, lba48); | ||
| 429 | if (capacity == 0) | ||
| 430 | goto out; | ||
| 431 | |||
| 432 | set = ide_disk_hpa_set_capacity(drive, set, lba48); | ||
| 433 | if (set) | ||
| 434 | return set; | ||
| 435 | out: | ||
| 436 | return drive->capacity64; | ||
| 437 | } | ||
| 438 | |||
| 395 | static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) | 439 | static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) |
| 396 | { | 440 | { |
| 397 | ide_drive_t *drive = q->queuedata; | 441 | ide_drive_t *drive = q->queuedata; |
| @@ -741,6 +785,7 @@ static int ide_disk_set_doorlock(ide_drive_t *drive, struct gendisk *disk, | |||
| 741 | 785 | ||
| 742 | const struct ide_disk_ops ide_ata_disk_ops = { | 786 | const struct ide_disk_ops ide_ata_disk_ops = { |
| 743 | .check = ide_disk_check, | 787 | .check = ide_disk_check, |
| 788 | .set_capacity = ide_disk_set_capacity, | ||
| 744 | .get_capacity = ide_disk_get_capacity, | 789 | .get_capacity = ide_disk_get_capacity, |
| 745 | .setup = ide_disk_setup, | 790 | .setup = ide_disk_setup, |
| 746 | .flush = ide_disk_flush, | 791 | .flush = ide_disk_flush, |
