diff options
Diffstat (limited to 'drivers/ide/ide-disk.c')
-rw-r--r-- | drivers/ide/ide-disk.c | 75 |
1 files changed, 63 insertions, 12 deletions
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index c6f7fcfb9d67..6a1de2169709 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,13 @@ 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 | if ((drive->dev_flags & IDE_DFLAG_NOHPA) == 0) |
354 | return; | ||
334 | 355 | ||
335 | if (set_max) { | 356 | set_max = ide_disk_hpa_set_capacity(drive, set_max, lba48); |
336 | drive->capacity64 = set_max; | 357 | if (set_max) |
337 | printk(KERN_INFO "%s: Host Protected Area disabled.\n", | 358 | printk(KERN_INFO "%s: Host Protected Area disabled.\n", |
338 | drive->name); | 359 | drive->name); |
339 | } | ||
340 | } | 360 | } |
341 | 361 | ||
342 | static int ide_disk_get_capacity(ide_drive_t *drive) | 362 | static int ide_disk_get_capacity(ide_drive_t *drive) |
@@ -358,6 +378,8 @@ static int ide_disk_get_capacity(ide_drive_t *drive) | |||
358 | drive->capacity64 = drive->cyl * drive->head * drive->sect; | 378 | drive->capacity64 = drive->cyl * drive->head * drive->sect; |
359 | } | 379 | } |
360 | 380 | ||
381 | drive->probed_capacity = drive->capacity64; | ||
382 | |||
361 | if (lba) { | 383 | if (lba) { |
362 | drive->dev_flags |= IDE_DFLAG_LBA; | 384 | drive->dev_flags |= IDE_DFLAG_LBA; |
363 | 385 | ||
@@ -376,7 +398,7 @@ static int ide_disk_get_capacity(ide_drive_t *drive) | |||
376 | "%llu sectors (%llu MB)\n", | 398 | "%llu sectors (%llu MB)\n", |
377 | drive->name, (unsigned long long)drive->capacity64, | 399 | drive->name, (unsigned long long)drive->capacity64, |
378 | sectors_to_MB(drive->capacity64)); | 400 | sectors_to_MB(drive->capacity64)); |
379 | drive->capacity64 = 1ULL << 28; | 401 | drive->probed_capacity = drive->capacity64 = 1ULL << 28; |
380 | } | 402 | } |
381 | 403 | ||
382 | if ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && | 404 | if ((drive->hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && |
@@ -392,6 +414,34 @@ static int ide_disk_get_capacity(ide_drive_t *drive) | |||
392 | return 0; | 414 | return 0; |
393 | } | 415 | } |
394 | 416 | ||
417 | static u64 ide_disk_set_capacity(ide_drive_t *drive, u64 capacity) | ||
418 | { | ||
419 | u64 set = min(capacity, drive->probed_capacity); | ||
420 | u16 *id = drive->id; | ||
421 | int lba48 = ata_id_lba48_enabled(id); | ||
422 | |||
423 | if ((drive->dev_flags & IDE_DFLAG_LBA) == 0 || | ||
424 | ata_id_hpa_enabled(id) == 0) | ||
425 | goto out; | ||
426 | |||
427 | /* | ||
428 | * according to the spec the SET MAX ADDRESS command shall be | ||
429 | * immediately preceded by a READ NATIVE MAX ADDRESS command | ||
430 | */ | ||
431 | capacity = ide_disk_hpa_get_native_capacity(drive, lba48); | ||
432 | if (capacity == 0) | ||
433 | goto out; | ||
434 | |||
435 | set = ide_disk_hpa_set_capacity(drive, set, lba48); | ||
436 | if (set) { | ||
437 | /* needed for ->resume to disable HPA */ | ||
438 | drive->dev_flags |= IDE_DFLAG_NOHPA; | ||
439 | return set; | ||
440 | } | ||
441 | out: | ||
442 | return drive->capacity64; | ||
443 | } | ||
444 | |||
395 | static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) | 445 | static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) |
396 | { | 446 | { |
397 | ide_drive_t *drive = q->queuedata; | 447 | ide_drive_t *drive = q->queuedata; |
@@ -428,14 +478,14 @@ static int set_multcount(ide_drive_t *drive, int arg) | |||
428 | if (arg < 0 || arg > (drive->id[ATA_ID_MAX_MULTSECT] & 0xff)) | 478 | if (arg < 0 || arg > (drive->id[ATA_ID_MAX_MULTSECT] & 0xff)) |
429 | return -EINVAL; | 479 | return -EINVAL; |
430 | 480 | ||
431 | if (drive->special.b.set_multmode) | 481 | if (drive->special_flags & IDE_SFLAG_SET_MULTMODE) |
432 | return -EBUSY; | 482 | return -EBUSY; |
433 | 483 | ||
434 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); | 484 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); |
435 | rq->cmd_type = REQ_TYPE_ATA_TASKFILE; | 485 | rq->cmd_type = REQ_TYPE_ATA_TASKFILE; |
436 | 486 | ||
437 | drive->mult_req = arg; | 487 | drive->mult_req = arg; |
438 | drive->special.b.set_multmode = 1; | 488 | drive->special_flags |= IDE_SFLAG_SET_MULTMODE; |
439 | error = blk_execute_rq(drive->queue, NULL, rq, 0); | 489 | error = blk_execute_rq(drive->queue, NULL, rq, 0); |
440 | blk_put_request(rq); | 490 | blk_put_request(rq); |
441 | 491 | ||
@@ -740,6 +790,7 @@ static int ide_disk_set_doorlock(ide_drive_t *drive, struct gendisk *disk, | |||
740 | 790 | ||
741 | const struct ide_disk_ops ide_ata_disk_ops = { | 791 | const struct ide_disk_ops ide_ata_disk_ops = { |
742 | .check = ide_disk_check, | 792 | .check = ide_disk_check, |
793 | .set_capacity = ide_disk_set_capacity, | ||
743 | .get_capacity = ide_disk_get_capacity, | 794 | .get_capacity = ide_disk_get_capacity, |
744 | .setup = ide_disk_setup, | 795 | .setup = ide_disk_setup, |
745 | .flush = ide_disk_flush, | 796 | .flush = ide_disk_flush, |