aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pci-acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/pci-acpi.c')
-rw-r--r--drivers/pci/pci-acpi.c79
1 files changed, 11 insertions, 68 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index c5792d622dc4..1af4008182fd 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -17,10 +17,9 @@
17 17
18#include <linux/pci-acpi.h> 18#include <linux/pci-acpi.h>
19#include <linux/pm_runtime.h> 19#include <linux/pm_runtime.h>
20#include <linux/pm_qos.h>
20#include "pci.h" 21#include "pci.h"
21 22
22static DEFINE_MUTEX(pci_acpi_pm_notify_mtx);
23
24/** 23/**
25 * pci_acpi_wake_bus - Wake-up notification handler for root buses. 24 * pci_acpi_wake_bus - Wake-up notification handler for root buses.
26 * @handle: ACPI handle of a device the notification is for. 25 * @handle: ACPI handle of a device the notification is for.
@@ -68,67 +67,6 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
68} 67}
69 68
70/** 69/**
71 * add_pm_notifier - Register PM notifier for given ACPI device.
72 * @dev: ACPI device to add the notifier for.
73 * @context: PCI device or bus to check for PME status if an event is signaled.
74 *
75 * NOTE: @dev need not be a run-wake or wake-up device to be a valid source of
76 * PM wake-up events. For example, wake-up events may be generated for bridges
77 * if one of the devices below the bridge is signaling PME, even if the bridge
78 * itself doesn't have a wake-up GPE associated with it.
79 */
80static acpi_status add_pm_notifier(struct acpi_device *dev,
81 acpi_notify_handler handler,
82 void *context)
83{
84 acpi_status status = AE_ALREADY_EXISTS;
85
86 mutex_lock(&pci_acpi_pm_notify_mtx);
87
88 if (dev->wakeup.flags.notifier_present)
89 goto out;
90
91 status = acpi_install_notify_handler(dev->handle,
92 ACPI_SYSTEM_NOTIFY,
93 handler, context);
94 if (ACPI_FAILURE(status))
95 goto out;
96
97 dev->wakeup.flags.notifier_present = true;
98
99 out:
100 mutex_unlock(&pci_acpi_pm_notify_mtx);
101 return status;
102}
103
104/**
105 * remove_pm_notifier - Unregister PM notifier from given ACPI device.
106 * @dev: ACPI device to remove the notifier from.
107 */
108static acpi_status remove_pm_notifier(struct acpi_device *dev,
109 acpi_notify_handler handler)
110{
111 acpi_status status = AE_BAD_PARAMETER;
112
113 mutex_lock(&pci_acpi_pm_notify_mtx);
114
115 if (!dev->wakeup.flags.notifier_present)
116 goto out;
117
118 status = acpi_remove_notify_handler(dev->handle,
119 ACPI_SYSTEM_NOTIFY,
120 handler);
121 if (ACPI_FAILURE(status))
122 goto out;
123
124 dev->wakeup.flags.notifier_present = false;
125
126 out:
127 mutex_unlock(&pci_acpi_pm_notify_mtx);
128 return status;
129}
130
131/**
132 * pci_acpi_add_bus_pm_notifier - Register PM notifier for given PCI bus. 70 * pci_acpi_add_bus_pm_notifier - Register PM notifier for given PCI bus.
133 * @dev: ACPI device to add the notifier for. 71 * @dev: ACPI device to add the notifier for.
134 * @pci_bus: PCI bus to walk checking for PME status if an event is signaled. 72 * @pci_bus: PCI bus to walk checking for PME status if an event is signaled.
@@ -136,7 +74,7 @@ static acpi_status remove_pm_notifier(struct acpi_device *dev,
136acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev, 74acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev,
137 struct pci_bus *pci_bus) 75 struct pci_bus *pci_bus)
138{ 76{
139 return add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus); 77 return acpi_add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus);
140} 78}
141 79
142/** 80/**
@@ -145,7 +83,7 @@ acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev,
145 */ 83 */
146acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev) 84acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev)
147{ 85{
148 return remove_pm_notifier(dev, pci_acpi_wake_bus); 86 return acpi_remove_pm_notifier(dev, pci_acpi_wake_bus);
149} 87}
150 88
151/** 89/**
@@ -156,7 +94,7 @@ acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev)
156acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev, 94acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev,
157 struct pci_dev *pci_dev) 95 struct pci_dev *pci_dev)
158{ 96{
159 return add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev); 97 return acpi_add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev);
160} 98}
161 99
162/** 100/**
@@ -165,7 +103,7 @@ acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev,
165 */ 103 */
166acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev) 104acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
167{ 105{
168 return remove_pm_notifier(dev, pci_acpi_wake_dev); 106 return acpi_remove_pm_notifier(dev, pci_acpi_wake_dev);
169} 107}
170 108
171phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle) 109phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)
@@ -257,11 +195,16 @@ static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state)
257 return -ENODEV; 195 return -ENODEV;
258 196
259 switch (state) { 197 switch (state) {
198 case PCI_D3cold:
199 if (dev_pm_qos_flags(&dev->dev, PM_QOS_FLAG_NO_POWER_OFF) ==
200 PM_QOS_FLAGS_ALL) {
201 error = -EBUSY;
202 break;
203 }
260 case PCI_D0: 204 case PCI_D0:
261 case PCI_D1: 205 case PCI_D1:
262 case PCI_D2: 206 case PCI_D2:
263 case PCI_D3hot: 207 case PCI_D3hot:
264 case PCI_D3cold:
265 error = acpi_bus_set_power(handle, state_conv[state]); 208 error = acpi_bus_set_power(handle, state_conv[state]);
266 } 209 }
267 210