aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/libata-acpi.c28
-rw-r--r--include/scsi/scsi_device.h1
2 files changed, 27 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
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index ba9698852321..aff7525de194 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -153,6 +153,7 @@ struct scsi_device {
153 unsigned no_read_capacity_16:1; /* Avoid READ_CAPACITY_16 cmds */ 153 unsigned no_read_capacity_16:1; /* Avoid READ_CAPACITY_16 cmds */
154 unsigned try_rc_10_first:1; /* Try READ_CAPACACITY_10 first */ 154 unsigned try_rc_10_first:1; /* Try READ_CAPACACITY_10 first */
155 unsigned is_visible:1; /* is the device visible in sysfs */ 155 unsigned is_visible:1; /* is the device visible in sysfs */
156 unsigned can_power_off:1; /* Device supports runtime power off */
156 157
157 DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */ 158 DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
158 struct list_head event_list; /* asserted events */ 159 struct list_head event_list; /* asserted events */