PM: core: Fix device_pm_check_callbacks()
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 19 Sep 2017 00:22:39 +0000 (02:22 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tue, 19 Sep 2017 20:58:27 +0000 (22:58 +0200)
The device_pm_check_callbacks() function doesn't check legacy
->suspend and ->resume callback pointers under the device's
bus type, class and driver, so in some cases it may set the
no_pm_callbacks flag for the device incorrectly and then the
callbacks may be skipped during system suspend/resume, which
shouldn't happen.

Fixes: aa8e54b55947 (PM / sleep: Go direct_complete if driver has no callbacks)
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Cc: 4.5+ <stable@vger.kernel.org> # 4.5+
drivers/base/power/main.c

index ea1732ed7a9d9071db73784c7e37d505ed8dea0a..770b1539a083d111ba1a65b569d3a75eaa81dd38 100644 (file)
@@ -1860,10 +1860,13 @@ void device_pm_check_callbacks(struct device *dev)
 {
        spin_lock_irq(&dev->power.lock);
        dev->power.no_pm_callbacks =
-               (!dev->bus || pm_ops_is_empty(dev->bus->pm)) &&
-               (!dev->class || pm_ops_is_empty(dev->class->pm)) &&
+               (!dev->bus || (pm_ops_is_empty(dev->bus->pm) &&
+                !dev->bus->suspend && !dev->bus->resume)) &&
+               (!dev->class || (pm_ops_is_empty(dev->class->pm) &&
+                !dev->class->suspend && !dev->class->resume)) &&
                (!dev->type || pm_ops_is_empty(dev->type->pm)) &&
                (!dev->pm_domain || pm_ops_is_empty(&dev->pm_domain->ops)) &&
-               (!dev->driver || pm_ops_is_empty(dev->driver->pm));
+               (!dev->driver || (pm_ops_is_empty(dev->driver->pm) &&
+                !dev->driver->suspend && !dev->driver->resume));
        spin_unlock_irq(&dev->power.lock);
 }