ACPI / PCI: Rework the setup and cleanup of device wakeup
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Sat, 22 Dec 2012 23:02:44 +0000 (00:02 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 3 Jan 2013 12:09:41 +0000 (13:09 +0100)
Currently, the ACPI wakeup capability of PCI devices is set up
in two different places, partially in acpi_pci_bind() where
runtime wakeup is initialized and partially in
platform_pci_wakeup_init(), where system wakeup is initialized.
The cleanup is only done in acpi_pci_unbind() and it only covers
runtime wakeup.

Use the new .setup() and .cleanup() callbacks in struct acpi_bus_type
to consolidate that code and do the setup and the cleanup each in one
place.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
Acked-by: Toshi Kani <toshi.kani@hp.com>
drivers/acpi/device_pm.c
drivers/acpi/pci_bind.c
drivers/pci/pci-acpi.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/probe.c
include/linux/acpi.h

index f09dc987cf17bce2ea762cdf902165cdbb7bd3d9..e4f6ac95595ca1411b93cad0eaae1310710c5c1f 100644 (file)
@@ -353,7 +353,7 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
  * acpi_dev_pm_get_node - Get ACPI device node for the given physical device.
  * @dev: Device to get the ACPI node for.
  */
-static struct acpi_device *acpi_dev_pm_get_node(struct device *dev)
+struct acpi_device *acpi_dev_pm_get_node(struct device *dev)
 {
        acpi_handle handle = DEVICE_ACPI_HANDLE(dev);
        struct acpi_device *adev;
index a1dee29beed328430491bdbff3cfe386692b06ba..bbddcc9c894fd5d0ac723367be158f59ea62e324 100644 (file)
@@ -43,8 +43,6 @@ static int acpi_pci_unbind(struct acpi_device *device)
        if (!dev)
                goto out;
 
-       device_set_run_wake(&dev->dev, false);
-       pci_acpi_remove_pm_notifier(device);
        acpi_power_resource_unregister_device(&dev->dev, device->handle);
 
        if (!dev->subordinate)
@@ -71,10 +69,7 @@ static int acpi_pci_bind(struct acpi_device *device)
        if (!dev)
                return 0;
 
-       pci_acpi_add_pm_notifier(device, dev);
        acpi_power_resource_register_device(&dev->dev, device->handle);
-       if (device->wakeup.flags.run_wake)
-               device_set_run_wake(&dev->dev, true);
 
        /*
         * Install the 'bind' function to facilitate callbacks for
index 1af4008182fd631ed3249cf3341798a650de3922..b98106c110e76d4b862e427ba31a2aa7c8582459 100644 (file)
@@ -283,7 +283,6 @@ static struct pci_platform_pm_ops acpi_pci_platform_pm = {
        .is_manageable = acpi_pci_power_manageable,
        .set_state = acpi_pci_set_power_state,
        .choose_state = acpi_pci_choose_state,
-       .can_wakeup = acpi_pci_can_wakeup,
        .sleep_wake = acpi_pci_sleep_wake,
        .run_wake = acpi_pci_run_wake,
 };
@@ -321,10 +320,39 @@ static int acpi_pci_find_root_bridge(struct device *dev, acpi_handle *handle)
        return 0;
 }
 
+static void acpi_pci_wakeup_setup(struct device *dev)
+{
+       struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+       struct pci_dev *pci_dev = to_pci_dev(dev);
+
+       if (!adev || !adev->wakeup.flags.valid)
+               return;
+
+       device_set_wakeup_capable(dev, true);
+       acpi_pci_sleep_wake(pci_dev, false);
+
+       pci_acpi_add_pm_notifier(adev, pci_dev);
+       if (adev->wakeup.flags.run_wake)
+               device_set_run_wake(dev, true);
+}
+
+static void acpi_pci_wakeup_cleanup(struct device *dev)
+{
+       struct acpi_device *adev = acpi_dev_pm_get_node(dev);
+
+       if (adev && adev->wakeup.flags.valid) {
+               device_set_wakeup_capable(dev, false);
+               device_set_run_wake(dev, false);
+               pci_acpi_remove_pm_notifier(adev);
+       }
+}
+
 static struct acpi_bus_type acpi_pci_bus = {
        .bus = &pci_bus_type,
        .find_device = acpi_pci_find_device,
        .find_bridge = acpi_pci_find_root_bridge,
+       .setup = acpi_pci_wakeup_setup,
+       .cleanup = acpi_pci_wakeup_cleanup,
 };
 
 static int __init acpi_pci_init(void)
index 5cb5820fae40147a29c79913cd1ebadcbfba1348..0c4f641b7be169841e0ec68bc7e7642fc6efaaf4 100644 (file)
@@ -450,7 +450,7 @@ static struct pci_platform_pm_ops *pci_platform_pm;
 int pci_set_platform_pm(struct pci_platform_pm_ops *ops)
 {
        if (!ops->is_manageable || !ops->set_state || !ops->choose_state
-           || !ops->sleep_wake || !ops->can_wakeup)
+           || !ops->sleep_wake)
                return -EINVAL;
        pci_platform_pm = ops;
        return 0;
@@ -473,11 +473,6 @@ static inline pci_power_t platform_pci_choose_state(struct pci_dev *dev)
                        pci_platform_pm->choose_state(dev) : PCI_POWER_ERROR;
 }
 
-static inline bool platform_pci_can_wakeup(struct pci_dev *dev)
-{
-       return pci_platform_pm ? pci_platform_pm->can_wakeup(dev) : false;
-}
-
 static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable)
 {
        return pci_platform_pm ?
@@ -1985,25 +1980,6 @@ void pci_pm_init(struct pci_dev *dev)
        }
 }
 
-/**
- * platform_pci_wakeup_init - init platform wakeup if present
- * @dev: PCI device
- *
- * Some devices don't have PCI PM caps but can still generate wakeup
- * events through platform methods (like ACPI events).  If @dev supports
- * platform wakeup events, set the device flag to indicate as much.  This
- * may be redundant if the device also supports PCI PM caps, but double
- * initialization should be safe in that case.
- */
-void platform_pci_wakeup_init(struct pci_dev *dev)
-{
-       if (!platform_pci_can_wakeup(dev))
-               return;
-
-       device_set_wakeup_capable(&dev->dev, true);
-       platform_pci_sleep_wake(dev, false);
-}
-
 static void pci_add_saved_cap(struct pci_dev *pci_dev,
        struct pci_cap_saved_state *new_cap)
 {
index e8518292826f0182bc23206f0b7e25fe88de858f..adfd172c5b9b53ea1797af3d10d7a958f844d777 100644 (file)
@@ -43,9 +43,6 @@ int pci_probe_reset_function(struct pci_dev *dev);
  *                platform; to be used during system-wide transitions from a
  *                sleeping state to the working state and vice versa
  *
- * @can_wakeup: returns 'true' if given device is capable of waking up the
- *              system from a sleeping state
- *
  * @sleep_wake: enables/disables the system wake up capability of given device
  *
  * @run_wake: enables/disables the platform to generate run-time wake-up events
@@ -59,7 +56,6 @@ struct pci_platform_pm_ops {
        bool (*is_manageable)(struct pci_dev *dev);
        int (*set_state)(struct pci_dev *dev, pci_power_t state);
        pci_power_t (*choose_state)(struct pci_dev *dev);
-       bool (*can_wakeup)(struct pci_dev *dev);
        int (*sleep_wake)(struct pci_dev *dev, bool enable);
        int (*run_wake)(struct pci_dev *dev, bool enable);
 };
@@ -74,7 +70,6 @@ extern void pci_wakeup_bus(struct pci_bus *bus);
 extern void pci_config_pm_runtime_get(struct pci_dev *dev);
 extern void pci_config_pm_runtime_put(struct pci_dev *dev);
 extern void pci_pm_init(struct pci_dev *dev);
-extern void platform_pci_wakeup_init(struct pci_dev *dev);
 extern void pci_allocate_cap_save_buffers(struct pci_dev *dev);
 void pci_free_cap_save_buffers(struct pci_dev *dev);
 
index 6186f03d84f37c8aa696d3df504e722a5cd36b38..2dcd22d9c816f98c681f572a2f48fbba7da5680b 100644 (file)
@@ -1280,7 +1280,6 @@ static void pci_init_capabilities(struct pci_dev *dev)
 
        /* Power Management */
        pci_pm_init(dev);
-       platform_pci_wakeup_init(dev);
 
        /* Vital Product Data */
        pci_vpd_pci22_init(dev);
index 3994d7790b2309d0ff8bc7ba8f518a75fe4ffd7a..8c1d6f2a2193973ea524d205fb57b13fc46f87b5 100644 (file)
@@ -526,9 +526,14 @@ static inline int acpi_subsys_resume_early(struct device *dev) { return 0; }
 #endif
 
 #if defined(CONFIG_ACPI) && defined(CONFIG_PM)
+struct acpi_device *acpi_dev_pm_get_node(struct device *dev);
 int acpi_dev_pm_attach(struct device *dev, bool power_on);
 void acpi_dev_pm_detach(struct device *dev, bool power_off);
 #else
+static inline struct acpi_device *acpi_dev_pm_get_node(struct device *dev)
+{
+       return NULL;
+}
 static inline int acpi_dev_pm_attach(struct device *dev, bool power_on)
 {
        return -ENODEV;