Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 166a2967 authored by Aaron Lu's avatar Aaron Lu Committed by Jeff Garzik
Browse files

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: default avatarAaron Lu <aaron.lu@amd.com>
Signed-off-by: default avatarLin Ming <ming.m.lin@intel.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent b1354cbb
Loading
Loading
Loading
Loading
+26 −2
Original line number Original line Diff line number Diff line
@@ -1000,7 +1000,10 @@ static void ata_acpi_add_pm_notifier(struct ata_device *dev)
		return;
		return;


	status = acpi_bus_get_device(handle, &acpi_dev);
	status = acpi_bus_get_device(handle, &acpi_dev);
	if (ACPI_SUCCESS(status)) {
	if (ACPI_FAILURE(status))
		return;

	if (dev->sdev->can_power_off) {
		acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
		acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
			ata_acpi_wake_dev, dev);
			ata_acpi_wake_dev, dev);
		device_set_run_wake(&dev->sdev->sdev_gendev, true);
		device_set_run_wake(&dev->sdev->sdev_gendev, true);
@@ -1018,7 +1021,10 @@ static void ata_acpi_remove_pm_notifier(struct ata_device *dev)
		return;
		return;


	status = acpi_bus_get_device(handle, &acpi_dev);
	status = acpi_bus_get_device(handle, &acpi_dev);
	if (ACPI_SUCCESS(status)) {
	if (ACPI_FAILURE(status))
		return;

	if (dev->sdev->can_power_off) {
		device_set_run_wake(&dev->sdev->sdev_gendev, false);
		device_set_run_wake(&dev->sdev->sdev_gendev, false);
		acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
		acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
			ata_acpi_wake_dev);
			ata_acpi_wake_dev);
@@ -1102,6 +1108,9 @@ static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev,
				acpi_handle *handle)
				acpi_handle *handle)
{
{
	struct ata_device *ata_dev;
	struct ata_device *ata_dev;
	acpi_status status;
	struct acpi_device *acpi_dev;
	struct acpi_device_power_state *states;


	if (ap->flags & ATA_FLAG_ACPI_SATA)
	if (ap->flags & ATA_FLAG_ACPI_SATA)
		ata_dev = &ap->link.device[sdev->channel];
		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,
	if (!*handle)
	if (!*handle)
		return -ENODEV;
		return -ENODEV;


	status = acpi_bus_get_device(*handle, &acpi_dev);
	if (ACPI_FAILURE(status))
		return 0;

	/*
	 * If firmware has _PS3 or _PR3 for this device,
	 * and this ata ODD device support device attention,
	 * it means this device can be powered off
	 */
	states = acpi_dev->power.states;
	if ((states[ACPI_STATE_D3_HOT].flags.valid ||
			states[ACPI_STATE_D3_COLD].flags.explicit_set) &&
			ata_dev->flags & ATA_DFLAG_DA)
		sdev->can_power_off = 1;

	return 0;
	return 0;
}
}


+1 −0
Original line number Original line Diff line number Diff line
@@ -153,6 +153,7 @@ struct scsi_device {
	unsigned no_read_capacity_16:1; /* Avoid READ_CAPACITY_16 cmds */
	unsigned no_read_capacity_16:1; /* Avoid READ_CAPACITY_16 cmds */
	unsigned try_rc_10_first:1;	/* Try READ_CAPACACITY_10 first */
	unsigned try_rc_10_first:1;	/* Try READ_CAPACACITY_10 first */
	unsigned is_visible:1;	/* is the device visible in sysfs */
	unsigned is_visible:1;	/* is the device visible in sysfs */
	unsigned can_power_off:1; /* Device supports runtime power off */


	DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
	DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
	struct list_head event_list;	/* asserted events */
	struct list_head event_list;	/* asserted events */