diff options
-rw-r--r-- | drivers/ata/libata-acpi.c | 28 | ||||
-rw-r--r-- | include/scsi/scsi_device.h | 1 |
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 */ |