diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2009-09-08 17:14:49 -0400 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-09-09 17:19:11 -0400 |
commit | e80bb09d2c73d76a2a4cd79e4a83802dd901c642 (patch) | |
tree | fff892db62dd092ab8e3d70d19d813d4979a2503 | |
parent | df8db91fc3b543d373afa61beef35b072eea1368 (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.c | 8 | ||||
-rw-r--r-- | include/linux/pci.h | 1 |
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. */ |