aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/device_pm.c80
-rw-r--r--drivers/acpi/pci_root.c2
-rw-r--r--drivers/pci/pci-acpi.c60
-rw-r--r--include/acpi/acpi_bus.h21
-rw-r--r--include/linux/pci-acpi.h13
5 files changed, 101 insertions, 75 deletions
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index 49a51277f81d..366de0b0c39b 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -367,29 +367,61 @@ EXPORT_SYMBOL(acpi_bus_power_manageable);
367#ifdef CONFIG_PM 367#ifdef CONFIG_PM
368static DEFINE_MUTEX(acpi_pm_notifier_lock); 368static DEFINE_MUTEX(acpi_pm_notifier_lock);
369 369
370static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
371{
372 struct acpi_device *adev;
373
374 if (val != ACPI_NOTIFY_DEVICE_WAKE)
375 return;
376
377 adev = acpi_bus_get_acpi_device(handle);
378 if (!adev)
379 return;
380
381 mutex_lock(&acpi_pm_notifier_lock);
382
383 if (adev->wakeup.flags.notifier_present) {
384 __pm_wakeup_event(adev->wakeup.ws, 0);
385 if (adev->wakeup.context.work.func)
386 queue_pm_work(&adev->wakeup.context.work);
387 }
388
389 mutex_unlock(&acpi_pm_notifier_lock);
390
391 acpi_bus_put_acpi_device(adev);
392}
393
370/** 394/**
371 * acpi_add_pm_notifier - Register PM notifier for given ACPI device. 395 * acpi_add_pm_notifier - Register PM notify handler for given ACPI device.
372 * @adev: ACPI device to add the notifier for. 396 * @adev: ACPI device to add the notify handler for.
373 * @context: Context information to pass to the notifier routine. 397 * @dev: Device to generate a wakeup event for while handling the notification.
398 * @work_func: Work function to execute when handling the notification.
374 * 399 *
375 * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of 400 * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of
376 * PM wakeup events. For example, wakeup events may be generated for bridges 401 * PM wakeup events. For example, wakeup events may be generated for bridges
377 * if one of the devices below the bridge is signaling wakeup, even if the 402 * if one of the devices below the bridge is signaling wakeup, even if the
378 * bridge itself doesn't have a wakeup GPE associated with it. 403 * bridge itself doesn't have a wakeup GPE associated with it.
379 */ 404 */
380acpi_status acpi_add_pm_notifier(struct acpi_device *adev, 405acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev,
381 acpi_notify_handler handler, void *context) 406 void (*work_func)(struct work_struct *work))
382{ 407{
383 acpi_status status = AE_ALREADY_EXISTS; 408 acpi_status status = AE_ALREADY_EXISTS;
384 409
410 if (!dev && !work_func)
411 return AE_BAD_PARAMETER;
412
385 mutex_lock(&acpi_pm_notifier_lock); 413 mutex_lock(&acpi_pm_notifier_lock);
386 414
387 if (adev->wakeup.flags.notifier_present) 415 if (adev->wakeup.flags.notifier_present)
388 goto out; 416 goto out;
389 417
390 status = acpi_install_notify_handler(adev->handle, 418 adev->wakeup.ws = wakeup_source_register(dev_name(&adev->dev));
391 ACPI_SYSTEM_NOTIFY, 419 adev->wakeup.context.dev = dev;
392 handler, context); 420 if (work_func)
421 INIT_WORK(&adev->wakeup.context.work, work_func);
422
423 status = acpi_install_notify_handler(adev->handle, ACPI_SYSTEM_NOTIFY,
424 acpi_pm_notify_handler, NULL);
393 if (ACPI_FAILURE(status)) 425 if (ACPI_FAILURE(status))
394 goto out; 426 goto out;
395 427
@@ -404,8 +436,7 @@ acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
404 * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device. 436 * acpi_remove_pm_notifier - Unregister PM notifier from given ACPI device.
405 * @adev: ACPI device to remove the notifier from. 437 * @adev: ACPI device to remove the notifier from.
406 */ 438 */
407acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, 439acpi_status acpi_remove_pm_notifier(struct acpi_device *adev)
408 acpi_notify_handler handler)
409{ 440{
410 acpi_status status = AE_BAD_PARAMETER; 441 acpi_status status = AE_BAD_PARAMETER;
411 442
@@ -416,10 +447,17 @@ acpi_status acpi_remove_pm_notifier(struct acpi_device *adev,
416 447
417 status = acpi_remove_notify_handler(adev->handle, 448 status = acpi_remove_notify_handler(adev->handle,
418 ACPI_SYSTEM_NOTIFY, 449 ACPI_SYSTEM_NOTIFY,
419 handler); 450 acpi_pm_notify_handler);
420 if (ACPI_FAILURE(status)) 451 if (ACPI_FAILURE(status))
421 goto out; 452 goto out;
422 453
454 if (adev->wakeup.context.work.func) {
455 cancel_work_sync(&adev->wakeup.context.work);
456 adev->wakeup.context.work.func = NULL;
457 }
458 adev->wakeup.context.dev = NULL;
459 wakeup_source_unregister(adev->wakeup.ws);
460
423 adev->wakeup.flags.notifier_present = false; 461 adev->wakeup.flags.notifier_present = false;
424 462
425 out: 463 out:
@@ -602,16 +640,15 @@ EXPORT_SYMBOL(acpi_pm_device_sleep_state);
602 640
603#ifdef CONFIG_PM_RUNTIME 641#ifdef CONFIG_PM_RUNTIME
604/** 642/**
605 * acpi_wakeup_device - Wakeup notification handler for ACPI devices. 643 * acpi_pm_notify_work_func - ACPI devices wakeup notification work function.
606 * @handle: ACPI handle of the device the notification is for. 644 * @work: Work item to handle.
607 * @event: Type of the signaled event.
608 * @context: Device corresponding to @handle.
609 */ 645 */
610static void acpi_wakeup_device(acpi_handle handle, u32 event, void *context) 646static void acpi_pm_notify_work_func(struct work_struct *work)
611{ 647{
612 struct device *dev = context; 648 struct device *dev;
613 649
614 if (event == ACPI_NOTIFY_DEVICE_WAKE && dev) { 650 dev = container_of(work, struct acpi_device_wakeup_context, work)->dev;
651 if (dev) {
615 pm_wakeup_event(dev, 0); 652 pm_wakeup_event(dev, 0);
616 pm_runtime_resume(dev); 653 pm_runtime_resume(dev);
617 } 654 }
@@ -677,8 +714,7 @@ int acpi_pm_device_run_wake(struct device *phys_dev, bool enable)
677} 714}
678EXPORT_SYMBOL(acpi_pm_device_run_wake); 715EXPORT_SYMBOL(acpi_pm_device_run_wake);
679#else 716#else
680static inline void acpi_wakeup_device(acpi_handle handle, u32 event, 717static inline void acpi_pm_notify_work_func(struct work_struct *work) {}
681 void *context) {}
682#endif /* CONFIG_PM_RUNTIME */ 718#endif /* CONFIG_PM_RUNTIME */
683 719
684#ifdef CONFIG_PM_SLEEP 720#ifdef CONFIG_PM_SLEEP
@@ -1048,7 +1084,7 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
1048 if (dev->pm_domain) 1084 if (dev->pm_domain)
1049 return -EEXIST; 1085 return -EEXIST;
1050 1086
1051 acpi_add_pm_notifier(adev, acpi_wakeup_device, dev); 1087 acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func);
1052 dev->pm_domain = &acpi_general_pm_domain; 1088 dev->pm_domain = &acpi_general_pm_domain;
1053 if (power_on) { 1089 if (power_on) {
1054 acpi_dev_pm_full_power(adev); 1090 acpi_dev_pm_full_power(adev);
@@ -1076,7 +1112,7 @@ void acpi_dev_pm_detach(struct device *dev, bool power_off)
1076 1112
1077 if (adev && dev->pm_domain == &acpi_general_pm_domain) { 1113 if (adev && dev->pm_domain == &acpi_general_pm_domain) {
1078 dev->pm_domain = NULL; 1114 dev->pm_domain = NULL;
1079 acpi_remove_pm_notifier(adev, acpi_wakeup_device); 1115 acpi_remove_pm_notifier(adev);
1080 if (power_off) { 1116 if (power_off) {
1081 /* 1117 /*
1082 * If the device's PM QoS resume latency limit or flags 1118 * If the device's PM QoS resume latency limit or flags
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index d388f13d48b4..e6ae603ed1a1 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -593,7 +593,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
593 if (no_aspm) 593 if (no_aspm)
594 pcie_no_aspm(); 594 pcie_no_aspm();
595 595
596 pci_acpi_add_bus_pm_notifier(device, root->bus); 596 pci_acpi_add_bus_pm_notifier(device);
597 if (device->wakeup.flags.run_wake) 597 if (device->wakeup.flags.run_wake)
598 device_set_run_wake(root->bus->bridge, true); 598 device_set_run_wake(root->bus->bridge, true);
599 599
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index ca4927ba8433..7b8b2298840a 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -18,31 +18,31 @@
18#include "pci.h" 18#include "pci.h"
19 19
20/** 20/**
21 * pci_acpi_wake_bus - Wake-up notification handler for root buses. 21 * pci_acpi_wake_bus - Root bus wakeup notification fork function.
22 * @handle: ACPI handle of a device the notification is for. 22 * @work: Work item to handle.
23 * @event: Type of the signaled event.
24 * @context: PCI root bus to wake up devices on.
25 */ 23 */
26static void pci_acpi_wake_bus(acpi_handle handle, u32 event, void *context) 24static void pci_acpi_wake_bus(struct work_struct *work)
27{ 25{
28 struct pci_bus *pci_bus = context; 26 struct acpi_device *adev;
27 struct acpi_pci_root *root;
29 28
30 if (event == ACPI_NOTIFY_DEVICE_WAKE && pci_bus) 29 adev = container_of(work, struct acpi_device, wakeup.context.work);
31 pci_pme_wakeup_bus(pci_bus); 30 root = acpi_driver_data(adev);
31 pci_pme_wakeup_bus(root->bus);
32} 32}
33 33
34/** 34/**
35 * pci_acpi_wake_dev - Wake-up notification handler for PCI devices. 35 * pci_acpi_wake_dev - PCI device wakeup notification work function.
36 * @handle: ACPI handle of a device the notification is for. 36 * @handle: ACPI handle of a device the notification is for.
37 * @event: Type of the signaled event. 37 * @work: Work item to handle.
38 * @context: PCI device object to wake up.
39 */ 38 */
40static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context) 39static void pci_acpi_wake_dev(struct work_struct *work)
41{ 40{
42 struct pci_dev *pci_dev = context; 41 struct acpi_device_wakeup_context *context;
42 struct pci_dev *pci_dev;
43 43
44 if (event != ACPI_NOTIFY_DEVICE_WAKE || !pci_dev) 44 context = container_of(work, struct acpi_device_wakeup_context, work);
45 return; 45 pci_dev = to_pci_dev(context->dev);
46 46
47 if (pci_dev->pme_poll) 47 if (pci_dev->pme_poll)
48 pci_dev->pme_poll = false; 48 pci_dev->pme_poll = false;
@@ -65,23 +65,12 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
65} 65}
66 66
67/** 67/**
68 * pci_acpi_add_bus_pm_notifier - Register PM notifier for given PCI bus. 68 * pci_acpi_add_bus_pm_notifier - Register PM notifier for root PCI bus.
69 * @dev: ACPI device to add the notifier for. 69 * @dev: PCI root bridge ACPI device.
70 * @pci_bus: PCI bus to walk checking for PME status if an event is signaled.
71 */ 70 */
72acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev, 71acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev)
73 struct pci_bus *pci_bus)
74{ 72{
75 return acpi_add_pm_notifier(dev, pci_acpi_wake_bus, pci_bus); 73 return acpi_add_pm_notifier(dev, NULL, pci_acpi_wake_bus);
76}
77
78/**
79 * pci_acpi_remove_bus_pm_notifier - Unregister PCI bus PM notifier.
80 * @dev: ACPI device to remove the notifier from.
81 */
82acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev)
83{
84 return acpi_remove_pm_notifier(dev, pci_acpi_wake_bus);
85} 74}
86 75
87/** 76/**
@@ -92,16 +81,7 @@ acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev)
92acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev, 81acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev,
93 struct pci_dev *pci_dev) 82 struct pci_dev *pci_dev)
94{ 83{
95 return acpi_add_pm_notifier(dev, pci_acpi_wake_dev, pci_dev); 84 return acpi_add_pm_notifier(dev, &pci_dev->dev, pci_acpi_wake_dev);
96}
97
98/**
99 * pci_acpi_remove_pm_notifier - Unregister PCI device PM notifier.
100 * @dev: ACPI device to remove the notifier from.
101 */
102acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
103{
104 return acpi_remove_pm_notifier(dev, pci_acpi_wake_dev);
105} 85}
106 86
107phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle) 87phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle)
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index b5714580801a..99780d46abb6 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -315,12 +315,19 @@ struct acpi_device_wakeup_flags {
315 u8 notifier_present:1; /* Wake-up notify handler has been installed */ 315 u8 notifier_present:1; /* Wake-up notify handler has been installed */
316}; 316};
317 317
318struct acpi_device_wakeup_context {
319 struct work_struct work;
320 struct device *dev;
321};
322
318struct acpi_device_wakeup { 323struct acpi_device_wakeup {
319 acpi_handle gpe_device; 324 acpi_handle gpe_device;
320 u64 gpe_number; 325 u64 gpe_number;
321 u64 sleep_state; 326 u64 sleep_state;
322 struct list_head resources; 327 struct list_head resources;
323 struct acpi_device_wakeup_flags flags; 328 struct acpi_device_wakeup_flags flags;
329 struct acpi_device_wakeup_context context;
330 struct wakeup_source *ws;
324 int prepare_count; 331 int prepare_count;
325}; 332};
326 333
@@ -510,20 +517,18 @@ int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state);
510int acpi_disable_wakeup_device_power(struct acpi_device *dev); 517int acpi_disable_wakeup_device_power(struct acpi_device *dev);
511 518
512#ifdef CONFIG_PM 519#ifdef CONFIG_PM
513acpi_status acpi_add_pm_notifier(struct acpi_device *adev, 520acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev,
514 acpi_notify_handler handler, void *context); 521 void (*work_func)(struct work_struct *work));
515acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, 522acpi_status acpi_remove_pm_notifier(struct acpi_device *adev);
516 acpi_notify_handler handler);
517int acpi_pm_device_sleep_state(struct device *, int *, int); 523int acpi_pm_device_sleep_state(struct device *, int *, int);
518#else 524#else
519static inline acpi_status acpi_add_pm_notifier(struct acpi_device *adev, 525static inline acpi_status acpi_add_pm_notifier(struct acpi_device *adev,
520 acpi_notify_handler handler, 526 struct device *dev,
521 void *context) 527 void (*work_func)(struct work_struct *work))
522{ 528{
523 return AE_SUPPORT; 529 return AE_SUPPORT;
524} 530}
525static inline acpi_status acpi_remove_pm_notifier(struct acpi_device *adev, 531static inline acpi_status acpi_remove_pm_notifier(struct acpi_device *adev)
526 acpi_notify_handler handler)
527{ 532{
528 return AE_SUPPORT; 533 return AE_SUPPORT;
529} 534}
diff --git a/include/linux/pci-acpi.h b/include/linux/pci-acpi.h
index 637a608ded0b..64dacb7288a6 100644
--- a/include/linux/pci-acpi.h
+++ b/include/linux/pci-acpi.h
@@ -11,12 +11,17 @@
11#include <linux/acpi.h> 11#include <linux/acpi.h>
12 12
13#ifdef CONFIG_ACPI 13#ifdef CONFIG_ACPI
14extern acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev, 14extern acpi_status pci_acpi_add_bus_pm_notifier(struct acpi_device *dev);
15 struct pci_bus *pci_bus); 15static inline acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev)
16extern acpi_status pci_acpi_remove_bus_pm_notifier(struct acpi_device *dev); 16{
17 return acpi_remove_pm_notifier(dev);
18}
17extern acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev, 19extern acpi_status pci_acpi_add_pm_notifier(struct acpi_device *dev,
18 struct pci_dev *pci_dev); 20 struct pci_dev *pci_dev);
19extern acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev); 21static inline acpi_status pci_acpi_remove_pm_notifier(struct acpi_device *dev)
22{
23 return acpi_remove_pm_notifier(dev);
24}
20extern phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle); 25extern phys_addr_t acpi_pci_root_get_mcfg_addr(acpi_handle handle);
21 26
22static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev) 27static inline acpi_handle acpi_find_root_bridge_handle(struct pci_dev *pdev)