pci subsystem wakeup handler. --- drivers/pci/pci-driver.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) Index: linux/drivers/pci/pci-driver.c =================================================================== --- linux.orig/drivers/pci/pci-driver.c 2008-09-08 13:55:56.000000000 +0800 +++ linux/drivers/pci/pci-driver.c 2008-09-08 14:24:42.000000000 +0800 @@ -472,12 +472,57 @@ static int pci_pm_resume_noirq(struct de return error; } +/* + * Called when dev is suspected to invoke a wakeup event, return 0 if yes + * */ +static int pci_pm_wakeup_event(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + int pme_pos = pci_find_capability(pdev, PCI_CAP_ID_PM); + struct pci_driver *drv = pdev->driver; + u16 reg16; + int spurious = 0; + int ret = -ENODEV; + + if (pme_pos == 0) { + /* + * Some USB devices haven't PME, but have specific registers to + * control wakeup + */ + goto out; + } + + /* clear PME status and disable PME to avoid interrupt flood */ + pci_read_config_word(pdev, pme_pos + PCI_PM_CTRL, ®16); + if (!(reg16 & PCI_PM_CTRL_PME_STATUS)) + return -ENODEV; + /* I see spurious GPE here, just ignore it for now */ + if (!(reg16 & PCI_PM_CTRL_PME_ENABLE)) + spurious = 1; + reg16 &= ~PCI_PM_CTRL_PME_ENABLE; + reg16 |= PCI_PM_CTRL_PME_STATUS; + pci_write_config_word(pdev, pme_pos + PCI_PM_CTRL, reg16); + + if (spurious) + return -ENODEV; + ret = 0; + /* This device invokes PME, gives driver a chance to do something */ +out: + if (drv && drv->pm && drv->pm->base.wakeup_event) { + if (!ret) /* ignore return value in this case */ + drv->pm->base.wakeup_event(&pdev->dev); + else + return drv->pm->base.wakeup_event(&pdev->dev); + } + return ret; +} #else /* !CONFIG_SUSPEND */ #define pci_pm_suspend NULL #define pci_pm_suspend_noirq NULL #define pci_pm_resume NULL #define pci_pm_resume_noirq NULL +#define pci_pm_wakeup_event NULL #endif /* !CONFIG_SUSPEND */ @@ -651,6 +696,7 @@ struct pm_ext_ops pci_pm_ops = { .thaw = pci_pm_thaw, .poweroff = pci_pm_poweroff, .restore = pci_pm_restore, + .wakeup_event = pci_pm_wakeup_event, }, .suspend_noirq = pci_pm_suspend_noirq, .resume_noirq = pci_pm_resume_noirq, -- _______________________________________________ linux-pm mailing list linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/linux-pm