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

Commit 8f8e5c3e authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'acpi-pm'

* acpi-pm:
  PM / core: Drop run_wake flag from struct dev_pm_info
  PCI / PM: Simplify device wakeup settings code
  PCI / PM: Drop pme_interrupt flag from struct pci_dev
  ACPI / PM: Consolidate device wakeup settings code
  ACPI / PM: Drop run_wake from struct acpi_device_wakeup_flags
  ACPI / sleep: EC-based wakeup from suspend-to-idle on recent systems
  platform: x86: intel-hid: Wake up the system from suspend-to-idle
  platform: x86: intel-vbtn: Wake up the system from suspend-to-idle
  ACPI / PM: Ignore spurious SCI wakeups from suspend-to-idle
  platform/x86: Add driver for ACPI INT0002 Virtual GPIO device
  PCI / PM: Restore PME Enable if skipping wakeup setup
  PM / sleep: Print timing information if debug is enabled
  ACPI / PM: Clean up device wakeup enable/disable code
  ACPI / PM: Change log level of wakeup-related message
  USB / PCI / PM: Allow the PCI core to do the resume cleanup
  ACPI / PM: Run wakeup notify handlers synchronously

Conflicts:
	drivers/base/power/main.c
parents 9a5f2c87 de3ef1eb
Loading
Loading
Loading
Loading
+2 −5
Original line number Diff line number Diff line
@@ -105,9 +105,9 @@ knows what to do to handle the device).

In particular, if the driver requires remote wakeup capability (i.e. hardware
mechanism allowing the device to request a change of its power state, such as
PCI PME) for proper functioning and device_run_wake() returns 'false' for the
PCI PME) for proper functioning and device_can_wakeup() returns 'false' for the
device, then ->runtime_suspend() should return -EBUSY.  On the other hand, if
device_run_wake() returns 'true' for the device and the device is put into a
device_can_wakeup() returns 'true' for the device and the device is put into a
low-power state during the execution of the suspend callback, it is expected
that remote wakeup will be enabled for the device.  Generally, remote wakeup
should be enabled for all input devices put into low-power states at run time.
@@ -253,9 +253,6 @@ defined in include/linux/pm.h:
      being executed for that device and it is not practical to wait for the
      suspend to complete; means "start a resume as soon as you've suspended"

  unsigned int run_wake;
    - set if the device is capable of generating runtime wake-up events

  enum rpm_status runtime_status;
    - the runtime PM status of the device; this field's initial value is
      RPM_SUSPENDED, which means that each device is initially regarded by the
+1 −1
Original line number Diff line number Diff line
@@ -782,7 +782,7 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume)
	if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
	    (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
            (battery->capacity_now <= battery->alarm)))
		pm_wakeup_event(&battery->device->dev, 0);
		acpi_pm_wakeup_event(&battery->device->dev);

	return result;
}
+3 −2
Original line number Diff line number Diff line
@@ -217,7 +217,7 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state)
	}

	if (state)
		pm_wakeup_event(&device->dev, 0);
		acpi_pm_wakeup_event(&device->dev);

	ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device);
	if (ret == NOTIFY_DONE)
@@ -402,7 +402,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
		} else {
			int keycode;

			pm_wakeup_event(&device->dev, 0);
			acpi_pm_wakeup_event(&device->dev);
			if (button->suspended)
				break;

@@ -534,6 +534,7 @@ static int acpi_button_add(struct acpi_device *device)
		lid_device = device;
	}

	device_init_wakeup(&device->dev, true);
	printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device));
	return 0;

+42 −60
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include <linux/pm_qos.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/suspend.h>

#include "internal.h"

@@ -385,6 +386,12 @@ EXPORT_SYMBOL(acpi_bus_power_manageable);
#ifdef CONFIG_PM
static DEFINE_MUTEX(acpi_pm_notifier_lock);

void acpi_pm_wakeup_event(struct device *dev)
{
	pm_wakeup_dev_event(dev, 0, acpi_s2idle_wakeup());
}
EXPORT_SYMBOL_GPL(acpi_pm_wakeup_event);

static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
{
	struct acpi_device *adev;
@@ -399,9 +406,9 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
	mutex_lock(&acpi_pm_notifier_lock);

	if (adev->wakeup.flags.notifier_present) {
		__pm_wakeup_event(adev->wakeup.ws, 0);
		if (adev->wakeup.context.work.func)
			queue_pm_work(&adev->wakeup.context.work);
		pm_wakeup_ws_event(adev->wakeup.ws, 0, acpi_s2idle_wakeup());
		if (adev->wakeup.context.func)
			adev->wakeup.context.func(&adev->wakeup.context);
	}

	mutex_unlock(&acpi_pm_notifier_lock);
@@ -413,7 +420,7 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
 * acpi_add_pm_notifier - Register PM notify handler for given ACPI device.
 * @adev: ACPI device to add the notify handler for.
 * @dev: Device to generate a wakeup event for while handling the notification.
 * @work_func: Work function to execute when handling the notification.
 * @func: Work function to execute when handling the notification.
 *
 * NOTE: @adev need not be a run-wake or wakeup device to be a valid source of
 * PM wakeup events.  For example, wakeup events may be generated for bridges
@@ -421,11 +428,11 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
 * bridge itself doesn't have a wakeup GPE associated with it.
 */
acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev,
				 void (*work_func)(struct work_struct *work))
			void (*func)(struct acpi_device_wakeup_context *context))
{
	acpi_status status = AE_ALREADY_EXISTS;

	if (!dev && !work_func)
	if (!dev && !func)
		return AE_BAD_PARAMETER;

	mutex_lock(&acpi_pm_notifier_lock);
@@ -435,8 +442,7 @@ acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev,

	adev->wakeup.ws = wakeup_source_register(dev_name(&adev->dev));
	adev->wakeup.context.dev = dev;
	if (work_func)
		INIT_WORK(&adev->wakeup.context.work, work_func);
	adev->wakeup.context.func = func;

	status = acpi_install_notify_handler(adev->handle, ACPI_SYSTEM_NOTIFY,
					     acpi_pm_notify_handler, NULL);
@@ -469,10 +475,7 @@ acpi_status acpi_remove_pm_notifier(struct acpi_device *adev)
	if (ACPI_FAILURE(status))
		goto out;

	if (adev->wakeup.context.work.func) {
		cancel_work_sync(&adev->wakeup.context.work);
		adev->wakeup.context.work.func = NULL;
	}
	adev->wakeup.context.func = NULL;
	adev->wakeup.context.dev = NULL;
	wakeup_source_unregister(adev->wakeup.ws);

@@ -493,6 +496,13 @@ bool acpi_bus_can_wakeup(acpi_handle handle)
}
EXPORT_SYMBOL(acpi_bus_can_wakeup);

bool acpi_pm_device_can_wakeup(struct device *dev)
{
	struct acpi_device *adev = ACPI_COMPANION(dev);

	return adev ? acpi_device_can_wakeup(adev) : false;
}

/**
 * acpi_dev_pm_get_state - Get preferred power state of ACPI device.
 * @dev: Device whose preferred target power state to return.
@@ -658,16 +668,15 @@ EXPORT_SYMBOL(acpi_pm_device_sleep_state);

/**
 * acpi_pm_notify_work_func - ACPI devices wakeup notification work function.
 * @work: Work item to handle.
 * @context: Device wakeup context.
 */
static void acpi_pm_notify_work_func(struct work_struct *work)
static void acpi_pm_notify_work_func(struct acpi_device_wakeup_context *context)
{
	struct device *dev;
	struct device *dev = context->dev;

	dev = container_of(work, struct acpi_device_wakeup_context, work)->dev;
	if (dev) {
		pm_wakeup_event(dev, 0);
		pm_runtime_resume(dev);
		pm_request_resume(dev);
	}
}

@@ -693,80 +702,53 @@ static int acpi_device_wakeup(struct acpi_device *adev, u32 target_state,
		acpi_status res;
		int error;

		if (adev->wakeup.flags.enabled)
			return 0;

		error = acpi_enable_wakeup_device_power(adev, target_state);
		if (error)
			return error;

		if (adev->wakeup.flags.enabled)
			return 0;

		res = acpi_enable_gpe(wakeup->gpe_device, wakeup->gpe_number);
		if (ACPI_SUCCESS(res)) {
			adev->wakeup.flags.enabled = 1;
		} else {
		if (ACPI_FAILURE(res)) {
			acpi_disable_wakeup_device_power(adev);
			return -EIO;
		}
	} else {
		if (adev->wakeup.flags.enabled) {
		adev->wakeup.flags.enabled = 1;
	} else if (adev->wakeup.flags.enabled) {
		acpi_disable_gpe(wakeup->gpe_device, wakeup->gpe_number);
			adev->wakeup.flags.enabled = 0;
		}
		acpi_disable_wakeup_device_power(adev);
		adev->wakeup.flags.enabled = 0;
	}
	return 0;
}

/**
 * acpi_pm_device_run_wake - Enable/disable remote wakeup for given device.
 * @dev: Device to enable/disable the platform to wake up.
 * acpi_pm_set_device_wakeup - Enable/disable remote wakeup for given device.
 * @dev: Device to enable/disable to generate wakeup events.
 * @enable: Whether to enable or disable the wakeup functionality.
 */
int acpi_pm_device_run_wake(struct device *phys_dev, bool enable)
{
	struct acpi_device *adev;

	if (!device_run_wake(phys_dev))
		return -EINVAL;

	adev = ACPI_COMPANION(phys_dev);
	if (!adev) {
		dev_dbg(phys_dev, "ACPI companion missing in %s!\n", __func__);
		return -ENODEV;
	}

	return acpi_device_wakeup(adev, ACPI_STATE_S0, enable);
}
EXPORT_SYMBOL(acpi_pm_device_run_wake);

#ifdef CONFIG_PM_SLEEP
/**
 * acpi_pm_device_sleep_wake - Enable or disable device to wake up the system.
 * @dev: Device to enable/desible to wake up the system from sleep states.
 * @enable: Whether to enable or disable @dev to wake up the system.
 */
int acpi_pm_device_sleep_wake(struct device *dev, bool enable)
int acpi_pm_set_device_wakeup(struct device *dev, bool enable)
{
	struct acpi_device *adev;
	int error;

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

	adev = ACPI_COMPANION(dev);
	if (!adev) {
		dev_dbg(dev, "ACPI companion missing in %s!\n", __func__);
		return -ENODEV;
	}

	if (!acpi_device_can_wakeup(adev))
		return -EINVAL;

	error = acpi_device_wakeup(adev, acpi_target_system_state(), enable);
	if (!error)
		dev_info(dev, "System wakeup %s by ACPI\n",
				enable ? "enabled" : "disabled");
		dev_dbg(dev, "Wakeup %s by ACPI\n", enable ? "enabled" : "disabled");

	return error;
}
#endif /* CONFIG_PM_SLEEP */
EXPORT_SYMBOL(acpi_pm_set_device_wakeup);

/**
 * acpi_dev_pm_low_power - Put ACPI device into a low-power state.
+1 −1
Original line number Diff line number Diff line
@@ -1835,7 +1835,7 @@ static int acpi_ec_suspend(struct device *dev)
	struct acpi_ec *ec =
		acpi_driver_data(to_acpi_device(dev));

	if (ec_freeze_events)
	if (acpi_sleep_no_ec_events() && ec_freeze_events)
		acpi_ec_disable_event(ec);
	return 0;
}
Loading