Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eb9d0fe4 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki Committed by Jesse Barnes
Browse files

PCI ACPI: Rework PCI handling of wake-up



* Introduce function acpi_pm_device_sleep_wake() for enabling and
  disabling the system wake-up capability of devices that are power
  manageable by ACPI.

* Introduce function acpi_bus_can_wakeup() allowing other (dependent)
  subsystems to check if ACPI is able to enable the system wake-up
  capability of given device.

* Introduce callback .sleep_wake() in struct pci_platform_pm_ops and
  for the ACPI PCI 'driver' make it use acpi_pm_device_sleep_wake().

* Introduce callback .can_wakeup() in struct pci_platform_pm_ops and
  for the ACPI 'driver' make it use acpi_bus_can_wakeup().

* Move the PME# handlig code out of pci_enable_wake() and split it
  into two functions, pci_pme_capable() and pci_pme_active(),
  allowing the caller to check if given device is capable of
  generating PME# from given power state and to enable/disable the
  device's PME# functionality, respectively.

* Modify pci_enable_wake() to use the new ACPI callbacks and the new
  PME#-related functions.

* Drop the generic .platform_enable_wakeup() callback that is not
  used any more.

* Introduce device_set_wakeup_capable() that will set the
  power.can_wakeup flag of given device.

* Rework PCI device PM initialization so that, if given device is
  capable of generating wake-up events, either natively through the
  PME# mechanism, or with the help of the platform, its
  power.can_wakeup flag is set and its power.should_wakeup flag is
  unset as appropriate.

* Make ACPI set the power.can_wakeup flag for devices found to be
  wake-up capable by it.

* Make the ACPI wake-up code enable/disable GPEs for devices that
  have the wakeup.flags.prepared flag set (which means that their
  wake-up power has been enabled).

Signed-off-by: default avatarRafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 0af4b8c4
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -306,6 +306,17 @@ bool acpi_bus_power_manageable(acpi_handle handle)

EXPORT_SYMBOL(acpi_bus_power_manageable);

bool acpi_bus_can_wakeup(acpi_handle handle)
{
	struct acpi_device *device;
	int result;

	result = acpi_bus_get_device(handle, &device);
	return result ? false : device->wakeup.flags.valid;
}

EXPORT_SYMBOL(acpi_bus_can_wakeup);

/* --------------------------------------------------------------------------
                                Event Management
   -------------------------------------------------------------------------- */
+2 −0
Original line number Diff line number Diff line
@@ -166,6 +166,8 @@ static int acpi_bind_one(struct device *dev, acpi_handle handle)
				"firmware_node");
		ret = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
				"physical_node");
		if (acpi_dev->wakeup.flags.valid)
			device_set_wakeup_capable(dev, true);
	}

	return 0;
+25 −0
Original line number Diff line number Diff line
@@ -468,6 +468,31 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p)
		*d_min_p = d_min;
	return d_max;
}

/**
 *	acpi_pm_device_sleep_wake - enable or disable the system wake-up
 *                                  capability of given device
 *	@dev: device to handle
 *	@enable: 'true' - enable, 'false' - disable the wake-up capability
 */
int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
{
	acpi_handle handle;
	struct acpi_device *adev;

	if (!device_may_wakeup(dev))
		return -EINVAL;

	handle = DEVICE_ACPI_HANDLE(dev);
	if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) {
		printk(KERN_DEBUG "ACPI handle has no context!\n");
		return -ENODEV;
	}

	return enable ?
		acpi_enable_wakeup_device_power(adev, acpi_target_sleep_state) :
		acpi_disable_wakeup_device_power(adev);
}
#endif

static void acpi_power_off_prepare(void)
+7 −4
Original line number Diff line number Diff line
@@ -66,13 +66,15 @@ void acpi_enable_wakeup_device(u8 sleep_state)
	list_for_each_safe(node, next, &acpi_wakeup_device_list) {
		struct acpi_device *dev =
			container_of(node, struct acpi_device, wakeup_list);

		if (!dev->wakeup.flags.valid)
			continue;

		/* If users want to disable run-wake GPE,
		 * we only disable it for wake and leave it for runtime
		 */
		if (!dev->wakeup.state.enabled ||
		    sleep_state > (u32) dev->wakeup.sleep_state) {
		if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared)
		    || sleep_state > (u32) dev->wakeup.sleep_state) {
			if (dev->wakeup.flags.run_wake) {
				spin_unlock(&acpi_device_lock);
				/* set_gpe_type will disable GPE, leave it like that */
@@ -110,8 +112,9 @@ void acpi_disable_wakeup_device(u8 sleep_state)

		if (!dev->wakeup.flags.valid)
			continue;
		if (!dev->wakeup.state.enabled ||
		    sleep_state > (u32) dev->wakeup.sleep_state) {

		if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared)
		    || sleep_state > (u32) dev->wakeup.sleep_state) {
			if (dev->wakeup.flags.run_wake) {
				spin_unlock(&acpi_device_lock);
				acpi_set_gpe_type(dev->wakeup.gpe_device,
+0 −3
Original line number Diff line number Diff line
@@ -6,9 +6,6 @@
#include <linux/string.h>
#include "power.h"

int (*platform_enable_wakeup)(struct device *dev, int is_on);


/*
 *	wakeup - Report/change current wakeup option for device
 *
Loading