diff options
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, |