summaryrefslogtreecommitdiffstats
path: root/runtime_pm_fixups.patch
blob: 78911581032d525f3bf4a14c5b7fe96f67603ce4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
Experimental fixes for the interactions between runtime PM and ACPI power
resources. Needs some work with upstream.

diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 310e3b9..371debe 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -329,7 +329,8 @@ int acpi_bus_set_power(acpi_handle handle, int state)
 				goto end;
 			}
 		}
-		if (device->power.flags.power_resources) {
+		if (device->power.flags.power_resources &&
+		    !device->wakeup.run_wake_count) {
 			result = acpi_power_transition(device, state);
 			if (result)
 				goto end;
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c
index 8b3cc6a..b013174 100644
--- a/drivers/acpi/pci_bind.c
+++ b/drivers/acpi/pci_bind.c
@@ -33,6 +33,8 @@
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 
+#include "internal.h"
+
 #define _COMPONENT		ACPI_PCI_COMPONENT
 ACPI_MODULE_NAME("pci_bind");
 
@@ -173,6 +175,8 @@ static int acpi_pci_bind(struct acpi_device *device)
 		device->ops.unbind = acpi_pci_unbind;
 	}
 
+	acpi_power_transition(device, acpi_power_get_inferred_state(device));
+
 	/*
 	 * Evaluate and parse _PRT, if exists.  This code allows parsing of
 	 * _PRT objects within the scope of non-bridge devices.  Note that
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 844c155..8a42ddf 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -394,7 +394,7 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
  *    State Wake) for the device, if present
  * 2. Shutdown down the power resources
  */
-int acpi_disable_wakeup_device_power(struct acpi_device *dev)
+int acpi_disable_wakeup_device_power(struct acpi_device *dev, int sleep_state)
 {
 	int i, err = 0;
 
@@ -417,6 +417,9 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
 	if (err)
 		goto out;
 
+	if (sleep_state == ACPI_STATE_S0)
+		goto out;
+
 	/* Close power resource */
 	for (i = 0; i < dev->wakeup.resources.count; i++) {
 		int ret = acpi_power_off_device(
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c
index 2c5cd02..6bf016b 100644
--- a/drivers/acpi/sleep.c
+++ b/drivers/acpi/sleep.c
@@ -670,7 +670,7 @@ int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
 
 	error = enable ?
 		acpi_enable_wakeup_device_power(adev, acpi_target_sleep_state) :
-		acpi_disable_wakeup_device_power(adev);
+		acpi_disable_wakeup_device_power(adev, acpi_target_sleep_state);
 	if (!error)
 		dev_info(dev, "wake-up capability %s by ACPI\n",
 				enable ? "enabled" : "disabled");
diff --git a/drivers/acpi/wakeup.c b/drivers/acpi/wakeup.c
index f62a50c..ff48a54 100644
--- a/drivers/acpi/wakeup.c
+++ b/drivers/acpi/wakeup.c
@@ -71,7 +71,7 @@ void acpi_disable_wakeup_devices(u8 sleep_state)
 				ACPI_GPE_DISABLE);
 
 		if (dev->wakeup.state.enabled)
-			acpi_disable_wakeup_device_power(dev);
+			acpi_disable_wakeup_device_power(dev, sleep_state);
 	}
 }
 
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 24e19c5..cd99494 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -302,7 +302,7 @@ static int acpi_dev_run_wake(struct device *phys_dev, bool enable)
 		if (!--dev->wakeup.run_wake_count) {
 			acpi_disable_gpe(dev->wakeup.gpe_device,
 					 dev->wakeup.gpe_number);
-			acpi_disable_wakeup_device_power(dev);
+			acpi_disable_wakeup_device_power(dev, ACPI_STATE_S0);
 		}
 	} else {
 		error = -EALREADY;
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 4de84ce..284f43c 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -387,7 +387,7 @@ struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle);
 #define DEVICE_ACPI_HANDLE(dev) ((acpi_handle)((dev)->archdata.acpi_handle))
 
 int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state);
-int acpi_disable_wakeup_device_power(struct acpi_device *dev);
+int acpi_disable_wakeup_device_power(struct acpi_device *dev, int state);
 
 #ifdef CONFIG_PM_OPS
 int acpi_pm_device_sleep_state(struct device *, int *);