Skip to content

Commit

Permalink
libata: tell scsi layer device supports runtime power off
Browse files Browse the repository at this point in the history
If ATA device supports "Device Attention", then tell scsi layer that
the device supports runtime power off.

Signed-off-by: Aaron Lu <aaron.lu@amd.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
  • Loading branch information
Aaron Lu authored and Jeff Garzik committed Jun 29, 2012
1 parent b1354cb commit 166a296
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 2 deletions.
28 changes: 26 additions & 2 deletions drivers/ata/libata-acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1000,7 +1000,10 @@ static void ata_acpi_add_pm_notifier(struct ata_device *dev)
return;

status = acpi_bus_get_device(handle, &acpi_dev);
if (ACPI_SUCCESS(status)) {
if (ACPI_FAILURE(status))
return;

if (dev->sdev->can_power_off) {
acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
ata_acpi_wake_dev, dev);
device_set_run_wake(&dev->sdev->sdev_gendev, true);
Expand All @@ -1018,7 +1021,10 @@ static void ata_acpi_remove_pm_notifier(struct ata_device *dev)
return;

status = acpi_bus_get_device(handle, &acpi_dev);
if (ACPI_SUCCESS(status)) {
if (ACPI_FAILURE(status))
return;

if (dev->sdev->can_power_off) {
device_set_run_wake(&dev->sdev->sdev_gendev, false);
acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
ata_acpi_wake_dev);
Expand Down Expand Up @@ -1102,6 +1108,9 @@ static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev,
acpi_handle *handle)
{
struct ata_device *ata_dev;
acpi_status status;
struct acpi_device *acpi_dev;
struct acpi_device_power_state *states;

if (ap->flags & ATA_FLAG_ACPI_SATA)
ata_dev = &ap->link.device[sdev->channel];
Expand All @@ -1113,6 +1122,21 @@ static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev,
if (!*handle)
return -ENODEV;

status = acpi_bus_get_device(*handle, &acpi_dev);
if (ACPI_FAILURE(status))
return 0;

/*
* If firmware has _PS3 or _PR3 for this device,
* and this ata ODD device support device attention,
* it means this device can be powered off
*/
states = acpi_dev->power.states;
if ((states[ACPI_STATE_D3_HOT].flags.valid ||
states[ACPI_STATE_D3_COLD].flags.explicit_set) &&
ata_dev->flags & ATA_DFLAG_DA)
sdev->can_power_off = 1;

return 0;
}

Expand Down
1 change: 1 addition & 0 deletions include/scsi/scsi_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ struct scsi_device {
unsigned no_read_capacity_16:1; /* Avoid READ_CAPACITY_16 cmds */
unsigned try_rc_10_first:1; /* Try READ_CAPACACITY_10 first */
unsigned is_visible:1; /* is the device visible in sysfs */
unsigned can_power_off:1; /* Device supports runtime power off */

DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
struct list_head event_list; /* asserted events */
Expand Down

0 comments on commit 166a296

Please sign in to comment.