diff options
author | Shaohua Li <shaohua.li@intel.com> | 2007-11-01 21:32:38 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2008-01-23 05:24:09 -0500 |
commit | bd3adca52bc43b72c75db3e4c7809d47923b154c (patch) | |
tree | ec42456926e50a4b0adf916ac1c5f39f76e057f8 | |
parent | ae8d4ee7ff429136c8b482c3b38ed994c021d3fc (diff) |
libata-acpi: add ACPI _PSx method
ACPI spec (ver 3.0a, p289) requires IDE power on/off executes ACPI _PSx
methods. As recently most PATA drivers use libata, this patch adds _PSx
method support in libata. ACPI spec doesn't mention if SATA requires the
same _PSx method.
Signed-off-by: Shaohua Li <shaohua.li@intel.com>
Acked-by: Len Brown <len.brown@intel.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r-- | drivers/ata/libata-acpi.c | 30 | ||||
-rw-r--r-- | drivers/ata/libata-eh.c | 3 | ||||
-rw-r--r-- | drivers/ata/libata.h | 3 |
3 files changed, 36 insertions, 0 deletions
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 7bf4befd96bc..ebc4dfcf2f19 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c | |||
@@ -776,6 +776,36 @@ void ata_acpi_on_resume(struct ata_port *ap) | |||
776 | } | 776 | } |
777 | 777 | ||
778 | /** | 778 | /** |
779 | * ata_acpi_set_state - set the port power state | ||
780 | * @ap: target ATA port | ||
781 | * @state: state, on/off | ||
782 | * | ||
783 | * This function executes the _PS0/_PS3 ACPI method to set the power state. | ||
784 | * ACPI spec requires _PS0 when IDE power on and _PS3 when power off | ||
785 | */ | ||
786 | void ata_acpi_set_state(struct ata_port *ap, pm_message_t state) | ||
787 | { | ||
788 | struct ata_device *dev; | ||
789 | |||
790 | if (!ap->acpi_handle || (ap->flags & ATA_FLAG_ACPI_SATA)) | ||
791 | return; | ||
792 | |||
793 | /* channel first and then drives for power on and vica versa | ||
794 | for power off */ | ||
795 | if (state.event == PM_EVENT_ON) | ||
796 | acpi_bus_set_power(ap->acpi_handle, ACPI_STATE_D0); | ||
797 | |||
798 | ata_link_for_each_dev(dev, &ap->link) { | ||
799 | if (dev->acpi_handle && ata_dev_enabled(dev)) | ||
800 | acpi_bus_set_power(dev->acpi_handle, | ||
801 | state.event == PM_EVENT_ON ? | ||
802 | ACPI_STATE_D0 : ACPI_STATE_D3); | ||
803 | } | ||
804 | if (state.event != PM_EVENT_ON) | ||
805 | acpi_bus_set_power(ap->acpi_handle, ACPI_STATE_D3); | ||
806 | } | ||
807 | |||
808 | /** | ||
779 | * ata_acpi_on_devcfg - ATA ACPI hook called on device donfiguration | 809 | * ata_acpi_on_devcfg - ATA ACPI hook called on device donfiguration |
780 | * @dev: target ATA device | 810 | * @dev: target ATA device |
781 | * | 811 | * |
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 21a81cd148e4..1d7faab64810 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
@@ -2747,6 +2747,7 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap) | |||
2747 | if (ap->ops->port_suspend) | 2747 | if (ap->ops->port_suspend) |
2748 | rc = ap->ops->port_suspend(ap, ap->pm_mesg); | 2748 | rc = ap->ops->port_suspend(ap, ap->pm_mesg); |
2749 | 2749 | ||
2750 | ata_acpi_set_state(ap, PMSG_SUSPEND); | ||
2750 | out: | 2751 | out: |
2751 | /* report result */ | 2752 | /* report result */ |
2752 | spin_lock_irqsave(ap->lock, flags); | 2753 | spin_lock_irqsave(ap->lock, flags); |
@@ -2792,6 +2793,8 @@ static void ata_eh_handle_port_resume(struct ata_port *ap) | |||
2792 | 2793 | ||
2793 | WARN_ON(!(ap->pflags & ATA_PFLAG_SUSPENDED)); | 2794 | WARN_ON(!(ap->pflags & ATA_PFLAG_SUSPENDED)); |
2794 | 2795 | ||
2796 | ata_acpi_set_state(ap, PMSG_ON); | ||
2797 | |||
2795 | if (ap->ops->port_resume) | 2798 | if (ap->ops->port_resume) |
2796 | rc = ap->ops->port_resume(ap); | 2799 | rc = ap->ops->port_resume(ap); |
2797 | 2800 | ||
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index 048e26cfb339..8cf0874f248b 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h | |||
@@ -114,6 +114,7 @@ extern int ata_acpi_on_suspend(struct ata_port *ap); | |||
114 | extern void ata_acpi_on_resume(struct ata_port *ap); | 114 | extern void ata_acpi_on_resume(struct ata_port *ap); |
115 | extern int ata_acpi_on_devcfg(struct ata_device *dev); | 115 | extern int ata_acpi_on_devcfg(struct ata_device *dev); |
116 | extern void ata_acpi_on_disable(struct ata_device *dev); | 116 | extern void ata_acpi_on_disable(struct ata_device *dev); |
117 | extern void ata_acpi_set_state(struct ata_port *ap, pm_message_t state); | ||
117 | #else | 118 | #else |
118 | static inline void ata_acpi_associate_sata_port(struct ata_port *ap) { } | 119 | static inline void ata_acpi_associate_sata_port(struct ata_port *ap) { } |
119 | static inline void ata_acpi_associate(struct ata_host *host) { } | 120 | static inline void ata_acpi_associate(struct ata_host *host) { } |
@@ -122,6 +123,8 @@ static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; } | |||
122 | static inline void ata_acpi_on_resume(struct ata_port *ap) { } | 123 | static inline void ata_acpi_on_resume(struct ata_port *ap) { } |
123 | static inline int ata_acpi_on_devcfg(struct ata_device *dev) { return 0; } | 124 | static inline int ata_acpi_on_devcfg(struct ata_device *dev) { return 0; } |
124 | static inline void ata_acpi_on_disable(struct ata_device *dev) { } | 125 | static inline void ata_acpi_on_disable(struct ata_device *dev) { } |
126 | static inline void ata_acpi_set_state(struct ata_port *ap, | ||
127 | pm_message_t state) { } | ||
125 | #endif | 128 | #endif |
126 | 129 | ||
127 | /* libata-scsi.c */ | 130 | /* libata-scsi.c */ |