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 | |
| 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>
| -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 */ |
