Commit 166a2967b45ede2e2e56f3ede3cd32053dc17812
Committed by
Jeff Garzik
1 parent
b1354cbb5b
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>
Showing 2 changed files with 27 additions and 2 deletions Side-by-side Diff
drivers/ata/libata-acpi.c
... | ... | @@ -1000,7 +1000,10 @@ |
1000 | 1000 | return; |
1001 | 1001 | |
1002 | 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 | 1007 | acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY, |
1005 | 1008 | ata_acpi_wake_dev, dev); |
1006 | 1009 | device_set_run_wake(&dev->sdev->sdev_gendev, true); |
... | ... | @@ -1018,7 +1021,10 @@ |
1018 | 1021 | return; |
1019 | 1022 | |
1020 | 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 | 1028 | device_set_run_wake(&dev->sdev->sdev_gendev, false); |
1023 | 1029 | acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, |
1024 | 1030 | ata_acpi_wake_dev); |
... | ... | @@ -1102,6 +1108,9 @@ |
1102 | 1108 | acpi_handle *handle) |
1103 | 1109 | { |
1104 | 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 | 1115 | if (ap->flags & ATA_FLAG_ACPI_SATA) |
1107 | 1116 | ata_dev = &ap->link.device[sdev->channel]; |
... | ... | @@ -1112,6 +1121,21 @@ |
1112 | 1121 | |
1113 | 1122 | if (!*handle) |
1114 | 1123 | return -ENODEV; |
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; | |
1115 | 1139 | |
1116 | 1140 | return 0; |
1117 | 1141 | } |
include/scsi/scsi_device.h
... | ... | @@ -153,6 +153,7 @@ |
153 | 153 | unsigned no_read_capacity_16:1; /* Avoid READ_CAPACITY_16 cmds */ |
154 | 154 | unsigned try_rc_10_first:1; /* Try READ_CAPACACITY_10 first */ |
155 | 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 | 158 | DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */ |
158 | 159 | struct list_head event_list; /* asserted events */ |