libata: implement on-demand HPA unlocking

Implement ata_scsi_unlock_native_capacity() which will be called
through SCSI layer when block layer notices that partitions on a
device extend beyond the end of the device. It requests EH to unlock
HPA, waits for completion and returns the current device capacity.

This allows libata to unlock HPA on demand instead of having to decide
whether to unlock upfront. Unlocking on demand is safer than
unlocking by upfront because some BIOSes write private data to the
area beyond HPA limit. This was suggested by Ben Hutchings.

Signed-off-by: Tejun Heo <tj@kernel.org>
Suggested-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>

authored by Tejun Heo and committed by Jeff Garzik d8d9129e 68939ce5

+32
+1
drivers/ata/libata-core.c
··· 6668 6668 EXPORT_SYMBOL_GPL(ata_link_next); 6669 6669 EXPORT_SYMBOL_GPL(ata_dev_next); 6670 6670 EXPORT_SYMBOL_GPL(ata_std_bios_param); 6671 + EXPORT_SYMBOL_GPL(ata_scsi_unlock_native_capacity); 6671 6672 EXPORT_SYMBOL_GPL(ata_host_init); 6672 6673 EXPORT_SYMBOL_GPL(ata_host_alloc); 6673 6674 EXPORT_SYMBOL_GPL(ata_host_alloc_pinfo);
+29
drivers/ata/libata-scsi.c
··· 415 415 } 416 416 417 417 /** 418 + * ata_scsi_unlock_native_capacity - unlock native capacity 419 + * @sdev: SCSI device to adjust device capacity for 420 + * 421 + * This function is called if a partition on @sdev extends beyond 422 + * the end of the device. It requests EH to unlock HPA. 423 + * 424 + * LOCKING: 425 + * Defined by the SCSI layer. Might sleep. 426 + */ 427 + void ata_scsi_unlock_native_capacity(struct scsi_device *sdev) 428 + { 429 + struct ata_port *ap = ata_shost_to_port(sdev->host); 430 + struct ata_device *dev; 431 + unsigned long flags; 432 + 433 + spin_lock_irqsave(ap->lock, flags); 434 + 435 + dev = ata_scsi_find_dev(ap, sdev); 436 + if (dev && dev->n_sectors < dev->n_native_sectors) { 437 + dev->flags |= ATA_DFLAG_UNLOCK_HPA; 438 + dev->link->eh_info.action |= ATA_EH_RESET; 439 + ata_port_schedule_eh(ap); 440 + } 441 + 442 + spin_unlock_irqrestore(ap->lock, flags); 443 + ata_port_wait_eh(ap); 444 + } 445 + 446 + /** 418 447 * ata_get_identity - Handler for HDIO_GET_IDENTITY ioctl 419 448 * @ap: target port 420 449 * @sdev: SCSI device to get identify data for
+2
include/linux/libata.h
··· 1023 1023 extern int ata_std_bios_param(struct scsi_device *sdev, 1024 1024 struct block_device *bdev, 1025 1025 sector_t capacity, int geom[]); 1026 + extern void ata_scsi_unlock_native_capacity(struct scsi_device *sdev); 1026 1027 extern int ata_scsi_slave_config(struct scsi_device *sdev); 1027 1028 extern void ata_scsi_slave_destroy(struct scsi_device *sdev); 1028 1029 extern int ata_scsi_change_queue_depth(struct scsi_device *sdev, ··· 1175 1174 .slave_configure = ata_scsi_slave_config, \ 1176 1175 .slave_destroy = ata_scsi_slave_destroy, \ 1177 1176 .bios_param = ata_std_bios_param, \ 1177 + .unlock_native_capacity = ata_scsi_unlock_native_capacity, \ 1178 1178 .sdev_attrs = ata_common_sdev_attrs 1179 1179 1180 1180 #define ATA_NCQ_SHT(drv_name) \