diff options
author | Aaron Lu <aaron.lu@amd.com> | 2012-06-25 04:13:09 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2012-06-29 11:38:45 -0400 |
commit | 166a2967b45ede2e2e56f3ede3cd32053dc17812 (patch) | |
tree | e1cb8b667281fc42512f1e4656292789e76bb5f3 /drivers/ata | |
parent | b1354cbb5bfce28f2e1ed28d77b362dfdfca638d (diff) |
libata: tell scsi layer device supports runtime power off
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>
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/libata-acpi.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index f36284e3290d..f1d6901de37d 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c | |||
@@ -1000,7 +1000,10 @@ static void ata_acpi_add_pm_notifier(struct ata_device *dev) | |||
1000 | return; | 1000 | return; |
1001 | 1001 | ||
1002 | status = acpi_bus_get_device(handle, &acpi_dev); | 1002 | status = acpi_bus_get_device(handle, &acpi_dev); |
1003 | if (ACPI_SUCCESS(status)) { | 1003 | if (ACPI_FAILURE(status)) |
1004 | return; | ||
1005 | |||
1006 | if (dev->sdev->can_power_off) { | ||
1004 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | 1007 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, |
1005 | ata_acpi_wake_dev, dev); | 1008 | ata_acpi_wake_dev, dev); |
1006 | device_set_run_wake(&dev->sdev->sdev_gendev, true); | 1009 | device_set_run_wake(&dev->sdev->sdev_gendev, true); |
@@ -1018,7 +1021,10 @@ static void ata_acpi_remove_pm_notifier(struct ata_device *dev) | |||
1018 | return; | 1021 | return; |
1019 | 1022 | ||
1020 | status = acpi_bus_get_device(handle, &acpi_dev); | 1023 | status = acpi_bus_get_device(handle, &acpi_dev); |
1021 | if (ACPI_SUCCESS(status)) { | 1024 | if (ACPI_FAILURE(status)) |
1025 | return; | ||
1026 | |||
1027 | if (dev->sdev->can_power_off) { | ||
1022 | device_set_run_wake(&dev->sdev->sdev_gendev, false); | 1028 | device_set_run_wake(&dev->sdev->sdev_gendev, false); |
1023 | acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, | 1029 | acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, |
1024 | ata_acpi_wake_dev); | 1030 | ata_acpi_wake_dev); |
@@ -1102,6 +1108,9 @@ static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev, | |||
1102 | acpi_handle *handle) | 1108 | acpi_handle *handle) |
1103 | { | 1109 | { |
1104 | struct ata_device *ata_dev; | 1110 | struct ata_device *ata_dev; |
1111 | acpi_status status; | ||
1112 | struct acpi_device *acpi_dev; | ||
1113 | struct acpi_device_power_state *states; | ||
1105 | 1114 | ||
1106 | if (ap->flags & ATA_FLAG_ACPI_SATA) | 1115 | if (ap->flags & ATA_FLAG_ACPI_SATA) |
1107 | ata_dev = &ap->link.device[sdev->channel]; | 1116 | ata_dev = &ap->link.device[sdev->channel]; |
@@ -1113,6 +1122,21 @@ static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev, | |||
1113 | if (!*handle) | 1122 | if (!*handle) |
1114 | return -ENODEV; | 1123 | return -ENODEV; |
1115 | 1124 | ||
1125 | status = acpi_bus_get_device(*handle, &acpi_dev); | ||
1126 | if (ACPI_FAILURE(status)) | ||
1127 | return 0; | ||
1128 | |||
1129 | /* | ||
1130 | * If firmware has _PS3 or _PR3 for this device, | ||
1131 | * and this ata ODD device support device attention, | ||
1132 | * it means this device can be powered off | ||
1133 | */ | ||
1134 | states = acpi_dev->power.states; | ||
1135 | if ((states[ACPI_STATE_D3_HOT].flags.valid || | ||
1136 | states[ACPI_STATE_D3_COLD].flags.explicit_set) && | ||
1137 | ata_dev->flags & ATA_DFLAG_DA) | ||
1138 | sdev->can_power_off = 1; | ||
1139 | |||
1116 | return 0; | 1140 | return 0; |
1117 | } | 1141 | } |
1118 | 1142 | ||