aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/pci-acpi.c211
-rw-r--r--drivers/pci/pci.c67
-rw-r--r--drivers/pci/pci.h7
3 files changed, 285 insertions, 0 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 7e2829538a4c..c0c73913833d 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -16,8 +16,144 @@
16#include <acpi/acpi_bus.h> 16#include <acpi/acpi_bus.h>
17 17
18#include <linux/pci-acpi.h> 18#include <linux/pci-acpi.h>
19#include <linux/pm_runtime.h>
19#include "pci.h" 20#include "pci.h"
20 21
22static DEFINE_MUTEX(pci_acpi_pm_notify_mtx);
23
24/**
25 * pci_acpi_wake_bus - Wake-up notification handler for root buses.
26 * @handle: ACPI handle of a device the notification is for.
27 * @event: Type of the signaled event.
28 * @context: PCI root bus to wake up devices on.
29 */
30static void pci_acpi_wake_bus(acpi_handle handle, u32 event, void *context)
31{
32 struct pci_bus *pci_bus = context;
33
34 if (event == ACPI_NOTIFY_DEVICE_WAKE && pci_bus)
35 pci_pme_wakeup_bus(pci_bus);
36}
37
38/**
39 * pci_acpi_wake_dev - Wake-up notification handler for PCI devices.
40 * @handle: ACPI handle of a device the notification is for.
41 * @event: Type of the signaled event.
42 * @context: PCI device object to wake up.
43 */
44static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
45{
46 struct pci_dev *pci_dev = context;
47
48 if (event == ACPI_NOTIFY_DEVICE_WAKE && pci_dev) {
49 pci_check_pme_status(pci_dev);
50 pm_runtime_resume(&pci_dev->dev);
51 if (pci_dev->subordinate)
52 pci_pme_wakeup_bus(pci_dev->subordinate);
53 }
54}
55
56/**
57 * add_pm_notifier - Register PM notifier for given ACPI device.
58 * @dev: ACPI device to add the notifier for.
59 * @context: PCI device or bus to check for PME status if an event is signaled.
60 *
61 * NOTE: @dev need not be a run-wake or wake-up device to be a valid source of
62 * PM wake-up events. For example, wake-up events may be generated for bridges
63 * if one of the devices below the bridge is signaling PME, even if the bridge
64 * itself doesn't have a wake-up GPE associated with it.
65 */
66static acpi_status add_pm_notifier(struct acpi_device *dev,
67 acpi_notify_handler handler,
68 void *context)
69{
70 acpi_status status = AE_ALREADY_EXISTS;
71
72 mutex_lock(&pci_acpi_pm_notify_mtx);
73
74 if (dev->wakeup.flags.notifier_present)
75 goto out;
76
77 status = acpi_install_notify_handler(dev->handle,
78 ACPI_SYSTEM_NOTIFY,
79 handler, context);
80 if (ACPI_FAILURE(status))
81 goto out;
82
83 dev->wakeup.flags.notifier_present = true;
84
85 out:
86 mutex_unlock(&pci_acpi_pm_notify_mtx);
87 return status;
88}
89
90/**
91 * remove_pm_notifier - Unregister PM notifier from given ACPI device.
92 * @dev: ACPI device to remove the notifier from.
93 */
94static acpi_status remove_pm_notifier(struct acpi_device *dev,
95 acpi_notify_handler handler)
96{
97 acpi_status status = AE_BAD_PARAMETER;
98
99 mutex_lock(&pci_acpi_pm_notify_mtx);
100
101 if (!dev->wakeup.flags.notifier_present)
102 goto out;
103
104 status = acpi_remove_notify_handler(dev->handle,
105 ACPI_SYSTEM_NOTIFY,
106 handler);
107 if (ACPI_FAILURE(status))
108 goto out;
109
110 dev->wakeup.flags.notifier_present = false;
111
112 out:
113 mutex_unlock(&pci_acpi_pm_notify_mtx);
114 return status;
115}
116
117/**
118 * pci_acpi_add_bus_pm_notifier - Register PM notifier for given PCI bus.
119 * @dev: ACPI device to add the notifier for.
120 * @pci_bus: PCI bus to walk checking for PME status if an event is signaled.
121 */
122acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev,
123 struct pci_bus *pci_bus)
124{
125 return add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus);
126}
127
128/**
129 * pci_acpi_remove_bus_pm_notifier - Unregister PCI bus PM notifier.
130 * @dev: ACPI device to remove the notifier from.
131 */
132acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev)
133{
134 return remove_pm_notifier(dev, pci_acpi_wake_bus);
135}
136
137/**
138 * pci_acpi_add_pm_notifier - Register PM notifier for given PCI device.
139 * @dev: ACPI device to add the notifier for.
140 * @pci_dev: PCI device to check for the PME status if an event is signaled.
141 */
142acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev,
143 struct pci_dev *pci_dev)
144{
145 return add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev);
146}
147
148/**
149 * pci_acpi_remove_pm_notifier - Unregister PCI device PM notifier.
150 * @dev: ACPI device to remove the notifier from.
151 */
152acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
153{
154 return remove_pm_notifier(dev, pci_acpi_wake_dev);
155}
156
21/* 157/*
22 * _SxD returns the D-state with the highest power 158 * _SxD returns the D-state with the highest power
23 * (lowest D-state number) supported in the S-state "x". 159 * (lowest D-state number) supported in the S-state "x".
@@ -131,12 +267,87 @@ static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable)
131 return 0; 267 return 0;
132} 268}
133 269
270/**
271 * acpi_dev_run_wake - Enable/disable wake-up for given device.
272 * @phys_dev: Device to enable/disable the platform to wake-up the system for.
273 * @enable: Whether enable or disable the wake-up functionality.
274 *
275 * Find the ACPI device object corresponding to @pci_dev and try to
276 * enable/disable the GPE associated with it.
277 */
278static int acpi_dev_run_wake(struct device *phys_dev, bool enable)
279{
280 struct acpi_device *dev;
281 acpi_handle handle;
282 int error = -ENODEV;
283
284 if (!device_run_wake(phys_dev))
285 return -EINVAL;
286
287 handle = DEVICE_ACPI_HANDLE(phys_dev);
288 if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &dev))) {
289 dev_dbg(phys_dev, "ACPI handle has no context in %s!\n",
290 __func__);
291 return -ENODEV;
292 }
293
294 if (enable) {
295 if (!dev->wakeup.run_wake_count++) {
296 acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0);
297 acpi_enable_gpe(dev->wakeup.gpe_device,
298 dev->wakeup.gpe_number,
299 ACPI_GPE_TYPE_RUNTIME);
300 }
301 } else if (dev->wakeup.run_wake_count > 0) {
302 if (!--dev->wakeup.run_wake_count) {
303 acpi_disable_gpe(dev->wakeup.gpe_device,
304 dev->wakeup.gpe_number,
305 ACPI_GPE_TYPE_RUNTIME);
306 acpi_disable_wakeup_device_power(dev);
307 }
308 } else {
309 error = -EALREADY;
310 }
311
312 return error;
313}
314
315static void acpi_pci_propagate_run_wake(struct pci_bus *bus, bool enable)
316{
317 while (bus->parent) {
318 struct pci_dev *bridge = bus->self;
319
320 if (bridge->pme_interrupt)
321 return;
322 if (!acpi_dev_run_wake(&bridge->dev, enable))
323 return;
324 bus = bus->parent;
325 }
326
327 /* We have reached the root bus. */
328 if (bus->bridge)
329 acpi_dev_run_wake(bus->bridge, enable);
330}
331
332static int acpi_pci_run_wake(struct pci_dev *dev, bool enable)
333{
334 if (dev->pme_interrupt)
335 return 0;
336
337 if (!acpi_dev_run_wake(&dev->dev, enable))
338 return 0;
339
340 acpi_pci_propagate_run_wake(dev->bus, enable);
341 return 0;
342}
343
134static struct pci_platform_pm_ops acpi_pci_platform_pm = { 344static struct pci_platform_pm_ops acpi_pci_platform_pm = {
135 .is_manageable = acpi_pci_power_manageable, 345 .is_manageable = acpi_pci_power_manageable,
136 .set_state = acpi_pci_set_power_state, 346 .set_state = acpi_pci_set_power_state,
137 .choose_state = acpi_pci_choose_state, 347 .choose_state = acpi_pci_choose_state,
138 .can_wakeup = acpi_pci_can_wakeup, 348 .can_wakeup = acpi_pci_can_wakeup,
139 .sleep_wake = acpi_pci_sleep_wake, 349 .sleep_wake = acpi_pci_sleep_wake,
350 .run_wake = acpi_pci_run_wake,
140}; 351};
141 352
142/* ACPI bus type */ 353/* ACPI bus type */
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 5723446544fd..df55a2f351b3 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -20,6 +20,7 @@
20#include <linux/pm_wakeup.h> 20#include <linux/pm_wakeup.h>
21#include <linux/interrupt.h> 21#include <linux/interrupt.h>
22#include <linux/device.h> 22#include <linux/device.h>
23#include <linux/pm_runtime.h>
23#include <asm/setup.h> 24#include <asm/setup.h>
24#include "pci.h" 25#include "pci.h"
25 26
@@ -462,6 +463,12 @@ static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable)
462 pci_platform_pm->sleep_wake(dev, enable) : -ENODEV; 463 pci_platform_pm->sleep_wake(dev, enable) : -ENODEV;
463} 464}
464 465
466static inline int platform_pci_run_wake(struct pci_dev *dev, bool enable)
467{
468 return pci_platform_pm ?
469 pci_platform_pm->run_wake(dev, enable) : -ENODEV;
470}
471
465/** 472/**
466 * pci_raw_set_power_state - Use PCI PM registers to set the power state of 473 * pci_raw_set_power_state - Use PCI PM registers to set the power state of
467 * given PCI device 474 * given PCI device
@@ -1230,6 +1237,31 @@ bool pci_check_pme_status(struct pci_dev *dev)
1230} 1237}
1231 1238
1232/** 1239/**
1240 * pci_pme_wakeup - Wake up a PCI device if its PME Status bit is set.
1241 * @dev: Device to handle.
1242 * @ign: Ignored.
1243 *
1244 * Check if @dev has generated PME and queue a resume request for it in that
1245 * case.
1246 */
1247static int pci_pme_wakeup(struct pci_dev *dev, void *ign)
1248{
1249 if (pci_check_pme_status(dev))
1250 pm_request_resume(&dev->dev);
1251 return 0;
1252}
1253
1254/**
1255 * pci_pme_wakeup_bus - Walk given bus and wake up devices on it, if necessary.
1256 * @bus: Top bus of the subtree to walk.
1257 */
1258void pci_pme_wakeup_bus(struct pci_bus *bus)
1259{
1260 if (bus)
1261 pci_walk_bus(bus, pci_pme_wakeup, NULL);
1262}
1263
1264/**
1233 * pci_pme_capable - check the capability of PCI device to generate PME# 1265 * pci_pme_capable - check the capability of PCI device to generate PME#
1234 * @dev: PCI device to handle. 1266 * @dev: PCI device to handle.
1235 * @state: PCI state from which device will issue PME#. 1267 * @state: PCI state from which device will issue PME#.
@@ -1434,6 +1466,41 @@ int pci_back_from_sleep(struct pci_dev *dev)
1434} 1466}
1435 1467
1436/** 1468/**
1469 * pci_dev_run_wake - Check if device can generate run-time wake-up events.
1470 * @dev: Device to check.
1471 *
1472 * Return true if the device itself is cabable of generating wake-up events
1473 * (through the platform or using the native PCIe PME) or if the device supports
1474 * PME and one of its upstream bridges can generate wake-up events.
1475 */
1476bool pci_dev_run_wake(struct pci_dev *dev)
1477{
1478 struct pci_bus *bus = dev->bus;
1479
1480 if (device_run_wake(&dev->dev))
1481 return true;
1482
1483 if (!dev->pme_support)
1484 return false;
1485
1486 while (bus->parent) {
1487 struct pci_dev *bridge = bus->self;
1488
1489 if (device_run_wake(&bridge->dev))
1490 return true;
1491
1492 bus = bus->parent;
1493 }
1494
1495 /* We have reached the root bus. */
1496 if (bus->bridge)
1497 return device_run_wake(bus->bridge);
1498
1499 return false;
1500}
1501EXPORT_SYMBOL_GPL(pci_dev_run_wake);
1502
1503/**
1437 * pci_pm_init - Initialize PM functions of given PCI device 1504 * pci_pm_init - Initialize PM functions of given PCI device
1438 * @dev: PCI device to handle. 1505 * @dev: PCI device to handle.
1439 */ 1506 */
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index b95b0a077d31..286c50821949 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -35,6 +35,10 @@ int pci_probe_reset_function(struct pci_dev *dev);
35 * 35 *
36 * @sleep_wake: enables/disables the system wake up capability of given device 36 * @sleep_wake: enables/disables the system wake up capability of given device
37 * 37 *
38 * @run_wake: enables/disables the platform to generate run-time wake-up events
39 * for given device (the device's wake-up capability has to be
40 * enabled by @sleep_wake for this feature to work)
41 *
38 * If given platform is generally capable of power managing PCI devices, all of 42 * If given platform is generally capable of power managing PCI devices, all of
39 * these callbacks are mandatory. 43 * these callbacks are mandatory.
40 */ 44 */
@@ -44,12 +48,15 @@ struct pci_platform_pm_ops {
44 pci_power_t (*choose_state)(struct pci_dev *dev); 48 pci_power_t (*choose_state)(struct pci_dev *dev);
45 bool (*can_wakeup)(struct pci_dev *dev); 49 bool (*can_wakeup)(struct pci_dev *dev);
46 int (*sleep_wake)(struct pci_dev *dev, bool enable); 50 int (*sleep_wake)(struct pci_dev *dev, bool enable);
51 int (*run_wake)(struct pci_dev *dev, bool enable);
47}; 52};
48 53
49extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops); 54extern int pci_set_platform_pm(struct pci_platform_pm_ops *ops);
50extern void pci_update_current_state(struct pci_dev *dev, pci_power_t state); 55extern void pci_update_current_state(struct pci_dev *dev, pci_power_t state);
51extern void pci_disable_enabled_device(struct pci_dev *dev); 56extern void pci_disable_enabled_device(struct pci_dev *dev);
52extern bool pci_check_pme_status(struct pci_dev *dev); 57extern bool pci_check_pme_status(struct pci_dev *dev);
58extern int __pci_pme_wakeup(struct pci_dev *dev, void *ign);
59extern void pci_pme_wakeup_bus(struct pci_bus *bus);
53extern void pci_pm_init(struct pci_dev *dev); 60extern void pci_pm_init(struct pci_dev *dev);
54extern void platform_pci_wakeup_init(struct pci_dev *dev); 61extern void platform_pci_wakeup_init(struct pci_dev *dev);
55extern void pci_allocate_cap_save_buffers(struct pci_dev *dev); 62extern void pci_allocate_cap_save_buffers(struct pci_dev *dev);