aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2009-09-08 17:14:49 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-09-09 17:19:11 -0400
commite80bb09d2c73d76a2a4cd79e4a83802dd901c642 (patch)
treefff892db62dd092ab8e3d70d19d813d4979a2503
parentdf8db91fc3b543d373afa61beef35b072eea1368 (diff)
PCI PM: Introduce device flag wakeup_prepared
Introduce a new PCI device flag, wakeup_prepared, to prevent PCI wake-up preparation code from being executed twice in a row for the same device and for the same purpose. Reviewed-by: Matthew Garrett <mjg59@srcf.ucam.org> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
-rw-r--r--drivers/pci/pci.c8
-rw-r--r--include/linux/pci.h1
2 files changed, 9 insertions, 0 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 84a6d6d30c5a..dcdfb2212ca3 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1225,6 +1225,10 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable)
1225 if (enable && !device_may_wakeup(&dev->dev)) 1225 if (enable && !device_may_wakeup(&dev->dev))
1226 return -EINVAL; 1226 return -EINVAL;
1227 1227
1228 /* Don't do the same thing twice in a row for one device. */
1229 if (!!enable == !!dev->wakeup_prepared)
1230 return 0;
1231
1228 /* 1232 /*
1229 * According to "PCI System Architecture" 4th ed. by Tom Shanley & Don 1233 * According to "PCI System Architecture" 4th ed. by Tom Shanley & Don
1230 * Anderson we should be doing PME# wake enable followed by ACPI wake 1234 * Anderson we should be doing PME# wake enable followed by ACPI wake
@@ -1241,9 +1245,12 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, bool enable)
1241 error = platform_pci_sleep_wake(dev, true); 1245 error = platform_pci_sleep_wake(dev, true);
1242 if (ret) 1246 if (ret)
1243 ret = error; 1247 ret = error;
1248 if (!ret)
1249 dev->wakeup_prepared = true;
1244 } else { 1250 } else {
1245 platform_pci_sleep_wake(dev, false); 1251 platform_pci_sleep_wake(dev, false);
1246 pci_pme_active(dev, false); 1252 pci_pme_active(dev, false);
1253 dev->wakeup_prepared = false;
1247 } 1254 }
1248 1255
1249 return ret; 1256 return ret;
@@ -1365,6 +1372,7 @@ void pci_pm_init(struct pci_dev *dev)
1365 int pm; 1372 int pm;
1366 u16 pmc; 1373 u16 pmc;
1367 1374
1375 dev->wakeup_prepared = false;
1368 dev->pm_cap = 0; 1376 dev->pm_cap = 0;
1369 1377
1370 /* find PCI PM capability in list */ 1378 /* find PCI PM capability in list */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index d80ed872a3c4..f5c7cd343e56 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -241,6 +241,7 @@ struct pci_dev {
241 unsigned int d1_support:1; /* Low power state D1 is supported */ 241 unsigned int d1_support:1; /* Low power state D1 is supported */
242 unsigned int d2_support:1; /* Low power state D2 is supported */ 242 unsigned int d2_support:1; /* Low power state D2 is supported */
243 unsigned int no_d1d2:1; /* Only allow D0 and D3 */ 243 unsigned int no_d1d2:1; /* Only allow D0 and D3 */
244 unsigned int wakeup_prepared:1;
244 245
245#ifdef CONFIG_PCIEASPM 246#ifdef CONFIG_PCIEASPM
246 struct pcie_link_state *link_state; /* ASPM link state. */ 247 struct pcie_link_state *link_state; /* ASPM link state. */