aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2011-07-06 04:51:40 -0400
committerRafael J. Wysocki <rjw@sisk.pl>2011-07-06 04:51:40 -0400
commiteea3fc0357eb89d0b2d1af37bdfb83eb4076a542 (patch)
treebe45aa2bc5370bdba7926f35dfdd73e8a6f464d0 /drivers/pci
parent632e270e01d8a1ee9e8ea56c83028727f17b1d17 (diff)
PCI / PM: Detect early wakeup in pci_pm_prepare()
A subsequent patch is going to move the invocation of pm_runtime_barrier() from dpm_prepare() to __device_suspend(). Consequently, early wakeup events resulting from runtime resume requests for wakeup devices queued up right before system suspend will only be detected after all of the subsystem-level .prepare() callbacks have run. However, the PCI bus type calls pm_runtime_get_sync() from its pci_pm_prepare() callback routine, so it would destroy the early wakeup events information regarding PCI devices. To prevent this from happening add an early wakeup detection mechanism, analogous to the one currently in dpm_prepare(), to pci_pm_prepare(). Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/pci-driver.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 46767c53917a..12d1e81a8abe 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -18,6 +18,7 @@
18#include <linux/sched.h> 18#include <linux/sched.h>
19#include <linux/cpu.h> 19#include <linux/cpu.h>
20#include <linux/pm_runtime.h> 20#include <linux/pm_runtime.h>
21#include <linux/suspend.h>
21#include "pci.h" 22#include "pci.h"
22 23
23struct pci_dynid { 24struct pci_dynid {
@@ -616,6 +617,21 @@ static int pci_pm_prepare(struct device *dev)
616 int error = 0; 617 int error = 0;
617 618
618 /* 619 /*
620 * If a PCI device configured to wake up the system from sleep states
621 * has been suspended at run time and there's a resume request pending
622 * for it, this is equivalent to the device signaling wakeup, so the
623 * system suspend operation should be aborted.
624 */
625 pm_runtime_get_noresume(dev);
626 if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
627 pm_wakeup_event(dev, 0);
628
629 if (pm_wakeup_pending()) {
630 pm_runtime_put_sync(dev);
631 return -EBUSY;
632 }
633
634 /*
619 * PCI devices suspended at run time need to be resumed at this 635 * PCI devices suspended at run time need to be resumed at this
620 * point, because in general it is necessary to reconfigure them for 636 * point, because in general it is necessary to reconfigure them for
621 * system suspend. Namely, if the device is supposed to wake up the 637 * system suspend. Namely, if the device is supposed to wake up the
@@ -624,7 +640,7 @@ static int pci_pm_prepare(struct device *dev)
624 * system from the sleep state, we'll have to prevent it from signaling 640 * system from the sleep state, we'll have to prevent it from signaling
625 * wake-up. 641 * wake-up.
626 */ 642 */
627 pm_runtime_get_sync(dev); 643 pm_runtime_resume(dev);
628 644
629 if (drv && drv->pm && drv->pm->prepare) 645 if (drv && drv->pm && drv->pm->prepare)
630 error = drv->pm->prepare(dev); 646 error = drv->pm->prepare(dev);