aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2009-06-07 07:52:52 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2009-06-07 07:52:52 -0400
commite957b60d1583022a0f7c03267d37fcae2ddb78b1 (patch)
tree5e9518eb38d427b9ac41c9b90b31b9b2453aebfc
parentdb429e9ec0f9dee2d8e50c154f04f29f880fc9d6 (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>
-rw-r--r--drivers/ide/ide-disk.c67
-rw-r--r--drivers/ide/ide-gd.c14
-rw-r--r--include/linux/ide.h4
3 files changed, 72 insertions, 13 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
305static void idedisk_check_hpa(ide_drive_t *drive) 305static 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
324static 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
333static 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
342static int ide_disk_get_capacity(ide_drive_t *drive) 359static 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
414static 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;
435out:
436 return drive->capacity64;
437}
438
395static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) 439static 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
742const struct ide_disk_ops ide_ata_disk_ops = { 786const 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,
diff --git a/drivers/ide/ide-gd.c b/drivers/ide/ide-gd.c
index 4b6b71e2cdf5..214119026b3f 100644
--- a/drivers/ide/ide-gd.c
+++ b/drivers/ide/ide-gd.c
@@ -287,6 +287,19 @@ static int ide_gd_media_changed(struct gendisk *disk)
287 return ret; 287 return ret;
288} 288}
289 289
290static unsigned long long ide_gd_set_capacity(struct gendisk *disk,
291 unsigned long long capacity)
292{
293 struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
294 ide_drive_t *drive = idkp->drive;
295 const struct ide_disk_ops *disk_ops = drive->disk_ops;
296
297 if (disk_ops->set_capacity)
298 return disk_ops->set_capacity(drive, capacity);
299
300 return drive->capacity64;
301}
302
290static int ide_gd_revalidate_disk(struct gendisk *disk) 303static int ide_gd_revalidate_disk(struct gendisk *disk)
291{ 304{
292 struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj); 305 struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
@@ -315,6 +328,7 @@ static struct block_device_operations ide_gd_ops = {
315 .locked_ioctl = ide_gd_ioctl, 328 .locked_ioctl = ide_gd_ioctl,
316 .getgeo = ide_gd_getgeo, 329 .getgeo = ide_gd_getgeo,
317 .media_changed = ide_gd_media_changed, 330 .media_changed = ide_gd_media_changed,
331 .set_capacity = ide_gd_set_capacity,
318 .revalidate_disk = ide_gd_revalidate_disk 332 .revalidate_disk = ide_gd_revalidate_disk
319}; 333};
320 334
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 9fed365a598b..e96ace12872a 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -397,6 +397,7 @@ struct ide_drive_s;
397struct ide_disk_ops { 397struct ide_disk_ops {
398 int (*check)(struct ide_drive_s *, const char *); 398 int (*check)(struct ide_drive_s *, const char *);
399 int (*get_capacity)(struct ide_drive_s *); 399 int (*get_capacity)(struct ide_drive_s *);
400 u64 (*set_capacity)(struct ide_drive_s *, u64);
400 void (*setup)(struct ide_drive_s *); 401 void (*setup)(struct ide_drive_s *);
401 void (*flush)(struct ide_drive_s *); 402 void (*flush)(struct ide_drive_s *);
402 int (*init_media)(struct ide_drive_s *, struct gendisk *); 403 int (*init_media)(struct ide_drive_s *, struct gendisk *);
@@ -568,8 +569,7 @@ struct ide_drive_s {
568 unsigned int drive_data; /* used by set_pio_mode/dev_select() */ 569 unsigned int drive_data; /* used by set_pio_mode/dev_select() */
569 unsigned int failures; /* current failure count */ 570 unsigned int failures; /* current failure count */
570 unsigned int max_failures; /* maximum allowed failure count */ 571 unsigned int max_failures; /* maximum allowed failure count */
571 u64 probed_capacity;/* initial reported media capacity (ide-cd only currently) */ 572 u64 probed_capacity;/* initial/native media capacity */
572
573 u64 capacity64; /* total number of sectors */ 573 u64 capacity64; /* total number of sectors */
574 574
575 int lun; /* logical unit */ 575 int lun; /* logical unit */