PCI: set device wakeup capable flag if platform support is present
authorJesse Barnes <jbarnes@virtuousgeek.org>
Wed, 17 Dec 2008 20:10:05 +0000 (12:10 -0800)
committerJesse Barnes <jbarnes@virtuousgeek.org>
Wed, 7 Jan 2009 19:13:07 +0000 (11:13 -0800)
When PCI devices are initialized, we check whether they support PCI PM
caps and set the device can_wakeup flag if so.  However, some devices
may have platform provided wakeup events rather than PCI PME signals, so
we need to set can_wakeup in that case too.  Doing so should allow
wakeups from many more devices, especially on cost constrained systems.

Reported-by: Alan Stern <stern@rowland.harvard.edu>
Tested-by: Joseph Chan <JosephChan@via.com.tw>
Acked-by: "Rafael J. Wysocki" <rjw@sisk.pl>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/probe.c

index 7e9c0f3936dd20e98bc606d013b54efb042a9c8c..1b807330e5005faa8f5f9c1b77d98ecc1bd406ac 100644 (file)
@@ -1285,6 +1285,26 @@ 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);
+       device_set_wakeup_enable(&dev->dev, false);
+       platform_pci_sleep_wake(dev, false);
+}
+
 /**
  * pci_add_save_buffer - allocate buffer for saving given capability registers
  * @dev: the PCI device
index d1e92d83aa066567279f1a8893cbd6d486914b06..65deed8bfc0615ffca9aff41e0ad71e697589efa 100644 (file)
@@ -45,6 +45,7 @@ struct pci_platform_pm_ops {
 
 extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops);
 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);
 
 extern int pci_user_read_config_byte(struct pci_dev *dev, int where, u8 *val);
index 2ee00962734b5df6da395a59608c6464d2d74691..303644614eea47010a924e221f775b3e7f030446 100644 (file)
@@ -965,6 +965,7 @@ 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);