aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorAaron Lu <aaron.lu@intel.com>2013-01-15 04:20:59 -0500
committerJeff Garzik <jgarzik@redhat.com>2013-01-21 15:41:12 -0500
commitf064a20dded807448669426c9bfb7d03aba5659c (patch)
tree9d56100107fded886a7f0987142bc4ee9eb62bba /drivers/ata
parentafe759511808cd5bb508b598007cf0c7b0ca8e08 (diff)
libata: move acpi notification code to zpodd
Since the ata acpi notification code introduced in commit 3bd46600a7a7e938c54df8cdbac9910668c7dfb0 is solely for ZPODD, and we now have a dedicated place for it, move these code there. And the ata_acpi_add_pm_notifier code is changed a little bit in that it is now invoked when scsi device is not bound with ACPI yet, so the way to get the acpi handle is different with the previous version. And the ata_acpi_add/remove_pm_notifier is also simplified a little bit in that it doesn't check if the acpi_device for the handle exists or not as the odd_can_poweroff function already checked that. Signed-off-by: Aaron Lu <aaron.lu@intel.com> Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/libata-acpi.c71
-rw-r--r--drivers/ata/libata-zpodd.c34
2 files changed, 34 insertions, 71 deletions
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index ef01ac07502e..446b4e761af0 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -974,57 +974,6 @@ void ata_acpi_on_disable(struct ata_device *dev)
974 ata_acpi_clear_gtf(dev); 974 ata_acpi_clear_gtf(dev);
975} 975}
976 976
977static void ata_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
978{
979 struct ata_device *ata_dev = context;
980
981 if (event == ACPI_NOTIFY_DEVICE_WAKE && ata_dev &&
982 pm_runtime_suspended(&ata_dev->sdev->sdev_gendev))
983 scsi_autopm_get_device(ata_dev->sdev);
984}
985
986static void ata_acpi_add_pm_notifier(struct ata_device *dev)
987{
988 struct acpi_device *acpi_dev;
989 acpi_handle handle;
990 acpi_status status;
991
992 handle = ata_dev_acpi_handle(dev);
993 if (!handle)
994 return;
995
996 status = acpi_bus_get_device(handle, &acpi_dev);
997 if (ACPI_FAILURE(status))
998 return;
999
1000 if (dev->sdev->can_power_off) {
1001 acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
1002 ata_acpi_wake_dev, dev);
1003 device_set_run_wake(&dev->sdev->sdev_gendev, true);
1004 }
1005}
1006
1007static void ata_acpi_remove_pm_notifier(struct ata_device *dev)
1008{
1009 struct acpi_device *acpi_dev;
1010 acpi_handle handle;
1011 acpi_status status;
1012
1013 handle = ata_dev_acpi_handle(dev);
1014 if (!handle)
1015 return;
1016
1017 status = acpi_bus_get_device(handle, &acpi_dev);
1018 if (ACPI_FAILURE(status))
1019 return;
1020
1021 if (dev->sdev->can_power_off) {
1022 device_set_run_wake(&dev->sdev->sdev_gendev, false);
1023 acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
1024 ata_acpi_wake_dev);
1025 }
1026}
1027
1028static void ata_acpi_register_power_resource(struct ata_device *dev) 977static void ata_acpi_register_power_resource(struct ata_device *dev)
1029{ 978{
1030 struct scsi_device *sdev = dev->sdev; 979 struct scsi_device *sdev = dev->sdev;
@@ -1057,13 +1006,11 @@ static void ata_acpi_unregister_power_resource(struct ata_device *dev)
1057 1006
1058void ata_acpi_bind(struct ata_device *dev) 1007void ata_acpi_bind(struct ata_device *dev)
1059{ 1008{
1060 ata_acpi_add_pm_notifier(dev);
1061 ata_acpi_register_power_resource(dev); 1009 ata_acpi_register_power_resource(dev);
1062} 1010}
1063 1011
1064void ata_acpi_unbind(struct ata_device *dev) 1012void ata_acpi_unbind(struct ata_device *dev)
1065{ 1013{
1066 ata_acpi_remove_pm_notifier(dev);
1067 ata_acpi_unregister_power_resource(dev); 1014 ata_acpi_unregister_power_resource(dev);
1068} 1015}
1069 1016
@@ -1105,9 +1052,6 @@ static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev,
1105 acpi_handle *handle) 1052 acpi_handle *handle)
1106{ 1053{
1107 struct ata_device *ata_dev; 1054 struct ata_device *ata_dev;
1108 acpi_status status;
1109 struct acpi_device *acpi_dev;
1110 struct acpi_device_power_state *states;
1111 1055
1112 if (ap->flags & ATA_FLAG_ACPI_SATA) { 1056 if (ap->flags & ATA_FLAG_ACPI_SATA) {
1113 if (!sata_pmp_attached(ap)) 1057 if (!sata_pmp_attached(ap))
@@ -1124,21 +1068,6 @@ static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev,
1124 if (!*handle) 1068 if (!*handle)
1125 return -ENODEV; 1069 return -ENODEV;
1126 1070
1127 status = acpi_bus_get_device(*handle, &acpi_dev);
1128 if (ACPI_FAILURE(status))
1129 return 0;
1130
1131 /*
1132 * If firmware has _PS3 or _PR3 for this device,
1133 * and this ata ODD device support device attention,
1134 * it means this device can be powered off
1135 */
1136 states = acpi_dev->power.states;
1137 if ((states[ACPI_STATE_D3_HOT].flags.valid ||
1138 states[ACPI_STATE_D3_COLD].flags.explicit_set) &&
1139 ata_dev->flags & ATA_DFLAG_DA)
1140 sdev->can_power_off = 1;
1141
1142 return 0; 1071 return 0;
1143} 1072}
1144 1073
diff --git a/drivers/ata/libata-zpodd.c b/drivers/ata/libata-zpodd.c
index 27eed2f09a8a..9a0d90d09d81 100644
--- a/drivers/ata/libata-zpodd.c
+++ b/drivers/ata/libata-zpodd.c
@@ -1,5 +1,7 @@
1#include <linux/libata.h> 1#include <linux/libata.h>
2#include <linux/cdrom.h> 2#include <linux/cdrom.h>
3#include <linux/pm_runtime.h>
4#include <scsi/scsi_device.h>
3 5
4#include "libata.h" 6#include "libata.h"
5 7
@@ -12,6 +14,10 @@ enum odd_mech_type {
12struct zpodd { 14struct zpodd {
13 enum odd_mech_type mech_type; /* init during probe, RO afterwards */ 15 enum odd_mech_type mech_type; /* init during probe, RO afterwards */
14 struct ata_device *dev; 16 struct ata_device *dev;
17
18 /* The following fields are synchronized by PM core. */
19 bool from_notify; /* resumed as a result of
20 * acpi wake notification */
15}; 21};
16 22
17/* Per the spec, only slot type and drawer type ODD can be supported */ 23/* Per the spec, only slot type and drawer type ODD can be supported */
@@ -68,6 +74,32 @@ static bool odd_can_poweroff(struct ata_device *ata_dev)
68 return acpi_device_can_poweroff(acpi_dev); 74 return acpi_device_can_poweroff(acpi_dev);
69} 75}
70 76
77static void zpodd_wake_dev(acpi_handle handle, u32 event, void *context)
78{
79 struct ata_device *ata_dev = context;
80 struct zpodd *zpodd = ata_dev->zpodd;
81 struct device *dev = &ata_dev->sdev->sdev_gendev;
82
83 if (event == ACPI_NOTIFY_DEVICE_WAKE && ata_dev &&
84 pm_runtime_suspended(dev)) {
85 zpodd->from_notify = true;
86 pm_runtime_resume(dev);
87 }
88}
89
90static void ata_acpi_add_pm_notifier(struct ata_device *dev)
91{
92 acpi_handle handle = ata_dev_acpi_handle(dev);
93 acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
94 zpodd_wake_dev, dev);
95}
96
97static void ata_acpi_remove_pm_notifier(struct ata_device *dev)
98{
99 acpi_handle handle = DEVICE_ACPI_HANDLE(&dev->sdev->sdev_gendev);
100 acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY, zpodd_wake_dev);
101}
102
71void zpodd_init(struct ata_device *dev) 103void zpodd_init(struct ata_device *dev)
72{ 104{
73 enum odd_mech_type mech_type; 105 enum odd_mech_type mech_type;
@@ -89,12 +121,14 @@ void zpodd_init(struct ata_device *dev)
89 121
90 zpodd->mech_type = mech_type; 122 zpodd->mech_type = mech_type;
91 123
124 ata_acpi_add_pm_notifier(dev);
92 zpodd->dev = dev; 125 zpodd->dev = dev;
93 dev->zpodd = zpodd; 126 dev->zpodd = zpodd;
94} 127}
95 128
96void zpodd_exit(struct ata_device *dev) 129void zpodd_exit(struct ata_device *dev)
97{ 130{
131 ata_acpi_remove_pm_notifier(dev);
98 kfree(dev->zpodd); 132 kfree(dev->zpodd);
99 dev->zpodd = NULL; 133 dev->zpodd = NULL;
100} 134}