diff options
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/libata-acpi.c | 76 | ||||
-rw-r--r-- | drivers/ata/libata-core.c | 29 | ||||
-rw-r--r-- | drivers/ata/libata-eh.c | 17 |
3 files changed, 83 insertions, 39 deletions
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 97094496127e..dfd529a30c20 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c | |||
@@ -836,9 +836,11 @@ void ata_acpi_on_resume(struct ata_port *ap) | |||
836 | } | 836 | } |
837 | } | 837 | } |
838 | 838 | ||
839 | static int ata_acpi_choose_suspend_state(struct ata_device *dev) | 839 | static int ata_acpi_choose_suspend_state(struct ata_device *dev, bool runtime) |
840 | { | 840 | { |
841 | int d_max_in = ACPI_STATE_D3_COLD; | 841 | int d_max_in = ACPI_STATE_D3_COLD; |
842 | if (!runtime) | ||
843 | goto out; | ||
842 | 844 | ||
843 | /* | 845 | /* |
844 | * For ATAPI, runtime D3 cold is only allowed | 846 | * For ATAPI, runtime D3 cold is only allowed |
@@ -848,53 +850,81 @@ static int ata_acpi_choose_suspend_state(struct ata_device *dev) | |||
848 | !(zpodd_dev_enabled(dev) && zpodd_zpready(dev))) | 850 | !(zpodd_dev_enabled(dev) && zpodd_zpready(dev))) |
849 | d_max_in = ACPI_STATE_D3_HOT; | 851 | d_max_in = ACPI_STATE_D3_HOT; |
850 | 852 | ||
853 | out: | ||
851 | return acpi_pm_device_sleep_state(&dev->sdev->sdev_gendev, | 854 | return acpi_pm_device_sleep_state(&dev->sdev->sdev_gendev, |
852 | NULL, d_max_in); | 855 | NULL, d_max_in); |
853 | } | 856 | } |
854 | 857 | ||
855 | /** | 858 | static void sata_acpi_set_state(struct ata_port *ap, pm_message_t state) |
856 | * ata_acpi_set_state - set the port power state | ||
857 | * @ap: target ATA port | ||
858 | * @state: state, on/off | ||
859 | * | ||
860 | * This function executes the _PS0/_PS3 ACPI method to set the power state. | ||
861 | * ACPI spec requires _PS0 when IDE power on and _PS3 when power off | ||
862 | */ | ||
863 | void ata_acpi_set_state(struct ata_port *ap, pm_message_t state) | ||
864 | { | 859 | { |
860 | bool runtime = PMSG_IS_AUTO(state); | ||
865 | struct ata_device *dev; | 861 | struct ata_device *dev; |
866 | acpi_handle handle; | 862 | acpi_handle handle; |
867 | int acpi_state; | 863 | int acpi_state; |
868 | 864 | ||
869 | /* channel first and then drives for power on and vica versa | ||
870 | for power off */ | ||
871 | handle = ata_ap_acpi_handle(ap); | ||
872 | if (handle && state.event == PM_EVENT_ON) | ||
873 | acpi_bus_set_power(handle, ACPI_STATE_D0); | ||
874 | |||
875 | ata_for_each_dev(dev, &ap->link, ENABLED) { | 865 | ata_for_each_dev(dev, &ap->link, ENABLED) { |
876 | handle = ata_dev_acpi_handle(dev); | 866 | handle = ata_dev_acpi_handle(dev); |
877 | if (!handle) | 867 | if (!handle) |
878 | continue; | 868 | continue; |
879 | 869 | ||
880 | if (state.event != PM_EVENT_ON) { | 870 | if (!(state.event & PM_EVENT_RESUME)) { |
881 | acpi_state = ata_acpi_choose_suspend_state(dev); | 871 | acpi_state = ata_acpi_choose_suspend_state(dev, runtime); |
882 | if (acpi_state == ACPI_STATE_D0) | 872 | if (acpi_state == ACPI_STATE_D0) |
883 | continue; | 873 | continue; |
884 | if (zpodd_dev_enabled(dev) && | 874 | if (runtime && zpodd_dev_enabled(dev) && |
885 | acpi_state == ACPI_STATE_D3_COLD) | 875 | acpi_state == ACPI_STATE_D3_COLD) |
886 | zpodd_enable_run_wake(dev); | 876 | zpodd_enable_run_wake(dev); |
887 | acpi_bus_set_power(handle, acpi_state); | 877 | acpi_bus_set_power(handle, acpi_state); |
888 | } else { | 878 | } else { |
889 | if (zpodd_dev_enabled(dev)) | 879 | if (runtime && zpodd_dev_enabled(dev)) |
890 | zpodd_disable_run_wake(dev); | 880 | zpodd_disable_run_wake(dev); |
891 | acpi_bus_set_power(handle, ACPI_STATE_D0); | 881 | acpi_bus_set_power(handle, ACPI_STATE_D0); |
892 | } | 882 | } |
893 | } | 883 | } |
884 | } | ||
885 | |||
886 | /* ACPI spec requires _PS0 when IDE power on and _PS3 when power off */ | ||
887 | static void pata_acpi_set_state(struct ata_port *ap, pm_message_t state) | ||
888 | { | ||
889 | struct ata_device *dev; | ||
890 | acpi_handle port_handle; | ||
891 | |||
892 | port_handle = ata_ap_acpi_handle(ap); | ||
893 | if (!port_handle) | ||
894 | return; | ||
895 | |||
896 | /* channel first and then drives for power on and vica versa | ||
897 | for power off */ | ||
898 | if (state.event & PM_EVENT_RESUME) | ||
899 | acpi_bus_set_power(port_handle, ACPI_STATE_D0); | ||
900 | |||
901 | ata_for_each_dev(dev, &ap->link, ENABLED) { | ||
902 | acpi_handle dev_handle = ata_dev_acpi_handle(dev); | ||
903 | if (!dev_handle) | ||
904 | continue; | ||
905 | |||
906 | acpi_bus_set_power(dev_handle, state.event & PM_EVENT_RESUME ? | ||
907 | ACPI_STATE_D0 : ACPI_STATE_D3); | ||
908 | } | ||
909 | |||
910 | if (!(state.event & PM_EVENT_RESUME)) | ||
911 | acpi_bus_set_power(port_handle, ACPI_STATE_D3); | ||
912 | } | ||
894 | 913 | ||
895 | handle = ata_ap_acpi_handle(ap); | 914 | /** |
896 | if (handle && state.event != PM_EVENT_ON) | 915 | * ata_acpi_set_state - set the port power state |
897 | acpi_bus_set_power(handle, ACPI_STATE_D3); | 916 | * @ap: target ATA port |
917 | * @state: state, on/off | ||
918 | * | ||
919 | * This function sets a proper ACPI D state for the device on | ||
920 | * system and runtime PM operations. | ||
921 | */ | ||
922 | void ata_acpi_set_state(struct ata_port *ap, pm_message_t state) | ||
923 | { | ||
924 | if (ap->flags & ATA_FLAG_ACPI_SATA) | ||
925 | sata_acpi_set_state(ap, state); | ||
926 | else | ||
927 | pata_acpi_set_state(ap, state); | ||
898 | } | 928 | } |
899 | 929 | ||
900 | /** | 930 | /** |
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 4b6fb48eb831..b7c972dc8b9b 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -5344,7 +5344,7 @@ static int __ata_port_suspend_common(struct ata_port *ap, pm_message_t mesg, int | |||
5344 | * | 5344 | * |
5345 | * http://thread.gmane.org/gmane.linux.ide/46764 | 5345 | * http://thread.gmane.org/gmane.linux.ide/46764 |
5346 | */ | 5346 | */ |
5347 | if (mesg.event == PM_EVENT_SUSPEND) | 5347 | if (mesg.event & PM_EVENT_SUSPEND) |
5348 | ehi_flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_NO_RECOVERY; | 5348 | ehi_flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_NO_RECOVERY; |
5349 | 5349 | ||
5350 | rc = ata_port_request_pm(ap, mesg, 0, ehi_flags, async); | 5350 | rc = ata_port_request_pm(ap, mesg, 0, ehi_flags, async); |
@@ -5382,27 +5382,28 @@ static int ata_port_poweroff(struct device *dev) | |||
5382 | return ata_port_suspend_common(dev, PMSG_HIBERNATE); | 5382 | return ata_port_suspend_common(dev, PMSG_HIBERNATE); |
5383 | } | 5383 | } |
5384 | 5384 | ||
5385 | static int __ata_port_resume_common(struct ata_port *ap, int *async) | 5385 | static int __ata_port_resume_common(struct ata_port *ap, pm_message_t mesg, |
5386 | int *async) | ||
5386 | { | 5387 | { |
5387 | int rc; | 5388 | int rc; |
5388 | 5389 | ||
5389 | rc = ata_port_request_pm(ap, PMSG_ON, ATA_EH_RESET, | 5390 | rc = ata_port_request_pm(ap, mesg, ATA_EH_RESET, |
5390 | ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, async); | 5391 | ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, async); |
5391 | return rc; | 5392 | return rc; |
5392 | } | 5393 | } |
5393 | 5394 | ||
5394 | static int ata_port_resume_common(struct device *dev) | 5395 | static int ata_port_resume_common(struct device *dev, pm_message_t mesg) |
5395 | { | 5396 | { |
5396 | struct ata_port *ap = to_ata_port(dev); | 5397 | struct ata_port *ap = to_ata_port(dev); |
5397 | 5398 | ||
5398 | return __ata_port_resume_common(ap, NULL); | 5399 | return __ata_port_resume_common(ap, mesg, NULL); |
5399 | } | 5400 | } |
5400 | 5401 | ||
5401 | static int ata_port_resume(struct device *dev) | 5402 | static int ata_port_resume(struct device *dev) |
5402 | { | 5403 | { |
5403 | int rc; | 5404 | int rc; |
5404 | 5405 | ||
5405 | rc = ata_port_resume_common(dev); | 5406 | rc = ata_port_resume_common(dev, PMSG_RESUME); |
5406 | if (!rc) { | 5407 | if (!rc) { |
5407 | pm_runtime_disable(dev); | 5408 | pm_runtime_disable(dev); |
5408 | pm_runtime_set_active(dev); | 5409 | pm_runtime_set_active(dev); |
@@ -5436,6 +5437,16 @@ static int ata_port_runtime_idle(struct device *dev) | |||
5436 | return pm_runtime_suspend(dev); | 5437 | return pm_runtime_suspend(dev); |
5437 | } | 5438 | } |
5438 | 5439 | ||
5440 | static int ata_port_runtime_suspend(struct device *dev) | ||
5441 | { | ||
5442 | return ata_port_suspend_common(dev, PMSG_AUTO_SUSPEND); | ||
5443 | } | ||
5444 | |||
5445 | static int ata_port_runtime_resume(struct device *dev) | ||
5446 | { | ||
5447 | return ata_port_resume_common(dev, PMSG_AUTO_RESUME); | ||
5448 | } | ||
5449 | |||
5439 | static const struct dev_pm_ops ata_port_pm_ops = { | 5450 | static const struct dev_pm_ops ata_port_pm_ops = { |
5440 | .suspend = ata_port_suspend, | 5451 | .suspend = ata_port_suspend, |
5441 | .resume = ata_port_resume, | 5452 | .resume = ata_port_resume, |
@@ -5444,8 +5455,8 @@ static const struct dev_pm_ops ata_port_pm_ops = { | |||
5444 | .poweroff = ata_port_poweroff, | 5455 | .poweroff = ata_port_poweroff, |
5445 | .restore = ata_port_resume, | 5456 | .restore = ata_port_resume, |
5446 | 5457 | ||
5447 | .runtime_suspend = ata_port_suspend, | 5458 | .runtime_suspend = ata_port_runtime_suspend, |
5448 | .runtime_resume = ata_port_resume_common, | 5459 | .runtime_resume = ata_port_runtime_resume, |
5449 | .runtime_idle = ata_port_runtime_idle, | 5460 | .runtime_idle = ata_port_runtime_idle, |
5450 | }; | 5461 | }; |
5451 | 5462 | ||
@@ -5462,7 +5473,7 @@ EXPORT_SYMBOL_GPL(ata_sas_port_async_suspend); | |||
5462 | 5473 | ||
5463 | int ata_sas_port_async_resume(struct ata_port *ap, int *async) | 5474 | int ata_sas_port_async_resume(struct ata_port *ap, int *async) |
5464 | { | 5475 | { |
5465 | return __ata_port_resume_common(ap, async); | 5476 | return __ata_port_resume_common(ap, PMSG_RESUME, async); |
5466 | } | 5477 | } |
5467 | EXPORT_SYMBOL_GPL(ata_sas_port_async_resume); | 5478 | EXPORT_SYMBOL_GPL(ata_sas_port_async_resume); |
5468 | 5479 | ||
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 50f3ef04809d..f9476fb3ac43 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
@@ -4029,7 +4029,7 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap) | |||
4029 | /* are we suspending? */ | 4029 | /* are we suspending? */ |
4030 | spin_lock_irqsave(ap->lock, flags); | 4030 | spin_lock_irqsave(ap->lock, flags); |
4031 | if (!(ap->pflags & ATA_PFLAG_PM_PENDING) || | 4031 | if (!(ap->pflags & ATA_PFLAG_PM_PENDING) || |
4032 | ap->pm_mesg.event == PM_EVENT_ON) { | 4032 | ap->pm_mesg.event & PM_EVENT_RESUME) { |
4033 | spin_unlock_irqrestore(ap->lock, flags); | 4033 | spin_unlock_irqrestore(ap->lock, flags); |
4034 | return; | 4034 | return; |
4035 | } | 4035 | } |
@@ -4040,10 +4040,13 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap) | |||
4040 | /* | 4040 | /* |
4041 | * If we have a ZPODD attached, check its zero | 4041 | * If we have a ZPODD attached, check its zero |
4042 | * power ready status before the port is frozen. | 4042 | * power ready status before the port is frozen. |
4043 | * Only needed for runtime suspend. | ||
4043 | */ | 4044 | */ |
4044 | ata_for_each_dev(dev, &ap->link, ENABLED) { | 4045 | if (PMSG_IS_AUTO(ap->pm_mesg)) { |
4045 | if (zpodd_dev_enabled(dev)) | 4046 | ata_for_each_dev(dev, &ap->link, ENABLED) { |
4046 | zpodd_on_suspend(dev); | 4047 | if (zpodd_dev_enabled(dev)) |
4048 | zpodd_on_suspend(dev); | ||
4049 | } | ||
4047 | } | 4050 | } |
4048 | 4051 | ||
4049 | /* tell ACPI we're suspending */ | 4052 | /* tell ACPI we're suspending */ |
@@ -4057,7 +4060,7 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap) | |||
4057 | if (ap->ops->port_suspend) | 4060 | if (ap->ops->port_suspend) |
4058 | rc = ap->ops->port_suspend(ap, ap->pm_mesg); | 4061 | rc = ap->ops->port_suspend(ap, ap->pm_mesg); |
4059 | 4062 | ||
4060 | ata_acpi_set_state(ap, PMSG_SUSPEND); | 4063 | ata_acpi_set_state(ap, ap->pm_mesg); |
4061 | out: | 4064 | out: |
4062 | /* report result */ | 4065 | /* report result */ |
4063 | spin_lock_irqsave(ap->lock, flags); | 4066 | spin_lock_irqsave(ap->lock, flags); |
@@ -4097,7 +4100,7 @@ static void ata_eh_handle_port_resume(struct ata_port *ap) | |||
4097 | /* are we resuming? */ | 4100 | /* are we resuming? */ |
4098 | spin_lock_irqsave(ap->lock, flags); | 4101 | spin_lock_irqsave(ap->lock, flags); |
4099 | if (!(ap->pflags & ATA_PFLAG_PM_PENDING) || | 4102 | if (!(ap->pflags & ATA_PFLAG_PM_PENDING) || |
4100 | ap->pm_mesg.event != PM_EVENT_ON) { | 4103 | !(ap->pm_mesg.event & PM_EVENT_RESUME)) { |
4101 | spin_unlock_irqrestore(ap->lock, flags); | 4104 | spin_unlock_irqrestore(ap->lock, flags); |
4102 | return; | 4105 | return; |
4103 | } | 4106 | } |
@@ -4116,7 +4119,7 @@ static void ata_eh_handle_port_resume(struct ata_port *ap) | |||
4116 | ata_for_each_dev(dev, link, ALL) | 4119 | ata_for_each_dev(dev, link, ALL) |
4117 | ata_ering_clear(&dev->ering); | 4120 | ata_ering_clear(&dev->ering); |
4118 | 4121 | ||
4119 | ata_acpi_set_state(ap, PMSG_ON); | 4122 | ata_acpi_set_state(ap, ap->pm_mesg); |
4120 | 4123 | ||
4121 | if (ap->ops->port_resume) | 4124 | if (ap->ops->port_resume) |
4122 | rc = ap->ops->port_resume(ap); | 4125 | rc = ap->ops->port_resume(ap); |