diff options
Diffstat (limited to 'drivers/pci/pci-acpi.c')
-rw-r--r-- | drivers/pci/pci-acpi.c | 90 |
1 files changed, 22 insertions, 68 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 47070cff508c..e70c1c7ba1bf 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -394,29 +394,26 @@ bool pciehp_is_native(struct pci_dev *pdev) | |||
394 | 394 | ||
395 | /** | 395 | /** |
396 | * pci_acpi_wake_bus - Root bus wakeup notification fork function. | 396 | * pci_acpi_wake_bus - Root bus wakeup notification fork function. |
397 | * @work: Work item to handle. | 397 | * @context: Device wakeup context. |
398 | */ | 398 | */ |
399 | static void pci_acpi_wake_bus(struct work_struct *work) | 399 | static void pci_acpi_wake_bus(struct acpi_device_wakeup_context *context) |
400 | { | 400 | { |
401 | struct acpi_device *adev; | 401 | struct acpi_device *adev; |
402 | struct acpi_pci_root *root; | 402 | struct acpi_pci_root *root; |
403 | 403 | ||
404 | adev = container_of(work, struct acpi_device, wakeup.context.work); | 404 | adev = container_of(context, struct acpi_device, wakeup.context); |
405 | root = acpi_driver_data(adev); | 405 | root = acpi_driver_data(adev); |
406 | pci_pme_wakeup_bus(root->bus); | 406 | pci_pme_wakeup_bus(root->bus); |
407 | } | 407 | } |
408 | 408 | ||
409 | /** | 409 | /** |
410 | * pci_acpi_wake_dev - PCI device wakeup notification work function. | 410 | * pci_acpi_wake_dev - PCI device wakeup notification work function. |
411 | * @handle: ACPI handle of a device the notification is for. | 411 | * @context: Device wakeup context. |
412 | * @work: Work item to handle. | ||
413 | */ | 412 | */ |
414 | static void pci_acpi_wake_dev(struct work_struct *work) | 413 | static void pci_acpi_wake_dev(struct acpi_device_wakeup_context *context) |
415 | { | 414 | { |
416 | struct acpi_device_wakeup_context *context; | ||
417 | struct pci_dev *pci_dev; | 415 | struct pci_dev *pci_dev; |
418 | 416 | ||
419 | context = container_of(work, struct acpi_device_wakeup_context, work); | ||
420 | pci_dev = to_pci_dev(context->dev); | 417 | pci_dev = to_pci_dev(context->dev); |
421 | 418 | ||
422 | if (pci_dev->pme_poll) | 419 | if (pci_dev->pme_poll) |
@@ -424,7 +421,7 @@ static void pci_acpi_wake_dev(struct work_struct *work) | |||
424 | 421 | ||
425 | if (pci_dev->current_state == PCI_D3cold) { | 422 | if (pci_dev->current_state == PCI_D3cold) { |
426 | pci_wakeup_event(pci_dev); | 423 | pci_wakeup_event(pci_dev); |
427 | pm_runtime_resume(&pci_dev->dev); | 424 | pm_request_resume(&pci_dev->dev); |
428 | return; | 425 | return; |
429 | } | 426 | } |
430 | 427 | ||
@@ -433,7 +430,7 @@ static void pci_acpi_wake_dev(struct work_struct *work) | |||
433 | pci_check_pme_status(pci_dev); | 430 | pci_check_pme_status(pci_dev); |
434 | 431 | ||
435 | pci_wakeup_event(pci_dev); | 432 | pci_wakeup_event(pci_dev); |
436 | pm_runtime_resume(&pci_dev->dev); | 433 | pm_request_resume(&pci_dev->dev); |
437 | 434 | ||
438 | pci_pme_wakeup_bus(pci_dev->subordinate); | 435 | pci_pme_wakeup_bus(pci_dev->subordinate); |
439 | } | 436 | } |
@@ -572,67 +569,29 @@ static pci_power_t acpi_pci_get_power_state(struct pci_dev *dev) | |||
572 | return state_conv[state]; | 569 | return state_conv[state]; |
573 | } | 570 | } |
574 | 571 | ||
575 | static bool acpi_pci_can_wakeup(struct pci_dev *dev) | 572 | static int acpi_pci_propagate_wakeup(struct pci_bus *bus, bool enable) |
576 | { | ||
577 | struct acpi_device *adev = ACPI_COMPANION(&dev->dev); | ||
578 | return adev ? acpi_device_can_wakeup(adev) : false; | ||
579 | } | ||
580 | |||
581 | static void acpi_pci_propagate_wakeup_enable(struct pci_bus *bus, bool enable) | ||
582 | { | ||
583 | while (bus->parent) { | ||
584 | if (!acpi_pm_device_sleep_wake(&bus->self->dev, enable)) | ||
585 | return; | ||
586 | bus = bus->parent; | ||
587 | } | ||
588 | |||
589 | /* We have reached the root bus. */ | ||
590 | if (bus->bridge) | ||
591 | acpi_pm_device_sleep_wake(bus->bridge, enable); | ||
592 | } | ||
593 | |||
594 | static int acpi_pci_sleep_wake(struct pci_dev *dev, bool enable) | ||
595 | { | ||
596 | if (acpi_pci_can_wakeup(dev)) | ||
597 | return acpi_pm_device_sleep_wake(&dev->dev, enable); | ||
598 | |||
599 | acpi_pci_propagate_wakeup_enable(dev->bus, enable); | ||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | static void acpi_pci_propagate_run_wake(struct pci_bus *bus, bool enable) | ||
604 | { | 573 | { |
605 | while (bus->parent) { | 574 | while (bus->parent) { |
606 | struct pci_dev *bridge = bus->self; | 575 | if (acpi_pm_device_can_wakeup(&bus->self->dev)) |
576 | return acpi_pm_set_device_wakeup(&bus->self->dev, enable); | ||
607 | 577 | ||
608 | if (bridge->pme_interrupt) | ||
609 | return; | ||
610 | if (!acpi_pm_device_run_wake(&bridge->dev, enable)) | ||
611 | return; | ||
612 | bus = bus->parent; | 578 | bus = bus->parent; |
613 | } | 579 | } |
614 | 580 | ||
615 | /* We have reached the root bus. */ | 581 | /* We have reached the root bus. */ |
616 | if (bus->bridge) | 582 | if (bus->bridge) { |
617 | acpi_pm_device_run_wake(bus->bridge, enable); | 583 | if (acpi_pm_device_can_wakeup(bus->bridge)) |
584 | return acpi_pm_set_device_wakeup(bus->bridge, enable); | ||
585 | } | ||
586 | return 0; | ||
618 | } | 587 | } |
619 | 588 | ||
620 | static int acpi_pci_run_wake(struct pci_dev *dev, bool enable) | 589 | static int acpi_pci_wakeup(struct pci_dev *dev, bool enable) |
621 | { | 590 | { |
622 | /* | 591 | if (acpi_pm_device_can_wakeup(&dev->dev)) |
623 | * Per PCI Express Base Specification Revision 2.0 section | 592 | return acpi_pm_set_device_wakeup(&dev->dev, enable); |
624 | * 5.3.3.2 Link Wakeup, platform support is needed for D3cold | ||
625 | * waking up to power on the main link even if there is PME | ||
626 | * support for D3cold | ||
627 | */ | ||
628 | if (dev->pme_interrupt && !dev->runtime_d3cold) | ||
629 | return 0; | ||
630 | |||
631 | if (!acpi_pm_device_run_wake(&dev->dev, enable)) | ||
632 | return 0; | ||
633 | 593 | ||
634 | acpi_pci_propagate_run_wake(dev->bus, enable); | 594 | return acpi_pci_propagate_wakeup(dev->bus, enable); |
635 | return 0; | ||
636 | } | 595 | } |
637 | 596 | ||
638 | static bool acpi_pci_need_resume(struct pci_dev *dev) | 597 | static bool acpi_pci_need_resume(struct pci_dev *dev) |
@@ -656,8 +615,7 @@ static const struct pci_platform_pm_ops acpi_pci_platform_pm = { | |||
656 | .set_state = acpi_pci_set_power_state, | 615 | .set_state = acpi_pci_set_power_state, |
657 | .get_state = acpi_pci_get_power_state, | 616 | .get_state = acpi_pci_get_power_state, |
658 | .choose_state = acpi_pci_choose_state, | 617 | .choose_state = acpi_pci_choose_state, |
659 | .sleep_wake = acpi_pci_sleep_wake, | 618 | .set_wakeup = acpi_pci_wakeup, |
660 | .run_wake = acpi_pci_run_wake, | ||
661 | .need_resume = acpi_pci_need_resume, | 619 | .need_resume = acpi_pci_need_resume, |
662 | }; | 620 | }; |
663 | 621 | ||
@@ -780,9 +738,7 @@ static void pci_acpi_setup(struct device *dev) | |||
780 | return; | 738 | return; |
781 | 739 | ||
782 | device_set_wakeup_capable(dev, true); | 740 | device_set_wakeup_capable(dev, true); |
783 | acpi_pci_sleep_wake(pci_dev, false); | 741 | acpi_pci_wakeup(pci_dev, false); |
784 | if (adev->wakeup.flags.run_wake) | ||
785 | device_set_run_wake(dev, true); | ||
786 | } | 742 | } |
787 | 743 | ||
788 | static void pci_acpi_cleanup(struct device *dev) | 744 | static void pci_acpi_cleanup(struct device *dev) |
@@ -793,10 +749,8 @@ static void pci_acpi_cleanup(struct device *dev) | |||
793 | return; | 749 | return; |
794 | 750 | ||
795 | pci_acpi_remove_pm_notifier(adev); | 751 | pci_acpi_remove_pm_notifier(adev); |
796 | if (adev->wakeup.flags.valid) { | 752 | if (adev->wakeup.flags.valid) |
797 | device_set_wakeup_capable(dev, false); | 753 | device_set_wakeup_capable(dev, false); |
798 | device_set_run_wake(dev, false); | ||
799 | } | ||
800 | } | 754 | } |
801 | 755 | ||
802 | static bool pci_acpi_bus_match(struct device *dev) | 756 | static bool pci_acpi_bus_match(struct device *dev) |