aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorAaron Lu <aaron.lu@amd.com>2012-06-25 04:13:09 -0400
committerJeff Garzik <jgarzik@redhat.com>2012-06-29 11:38:45 -0400
commit166a2967b45ede2e2e56f3ede3cd32053dc17812 (patch)
treee1cb8b667281fc42512f1e4656292789e76bb5f3 /drivers/ata
parentb1354cbb5bfce28f2e1ed28d77b362dfdfca638d (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.c28
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