aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-zpodd.c
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/libata-zpodd.c
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/libata-zpodd.c')
-rw-r--r--drivers/ata/libata-zpodd.c34
1 files changed, 34 insertions, 0 deletions
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}