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

Commit 3dbeb448 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'pm-sleep'

* pm-sleep:
  PM: sleep: Drop dev_pm_skip_next_resume_phases()
  ACPI: PM: Drop unused function and function header
  ACPI: PM: Introduce "poweroff" callbacks for ACPI PM domain and LPSS
  ACPI: PM: Simplify and fix PM domain hibernation callbacks
  PCI: PM: Simplify bus-level hibernation callbacks
  PM: ACPI/PCI: Resume all devices during hibernation
  kernel: power: swap: use kzalloc() instead of kmalloc() followed by memset()
  PM: sleep: Update struct wakeup_source documentation
  drivers: base: power: remove wakeup_sources_stats_dentry variable
  PM: suspend: Rename pm_suspend_via_s2idle()
  PM: sleep: Show how long dpm_suspend_start() and dpm_suspend_end() take
  PM: hibernate: powerpc: Expose pfn_is_nosave() prototype
parents 50e163d4 02bd45a2
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
 */

#include <linux/mm.h>
#include <linux/suspend.h>
#include <asm/page.h>
#include <asm/sections.h>

+0 −1
Original line number Diff line number Diff line
@@ -63,7 +63,6 @@ void __init startup_init(void);
void die(struct pt_regs *regs, const char *str);
int setup_profiling_timer(unsigned int multiplier);
void __init time_init(void);
int pfn_is_nosave(unsigned long);
void s390_early_resume(void);
unsigned long prepare_ftrace_return(unsigned long parent, unsigned long sp, unsigned long ip);

+99 −12
Original line number Diff line number Diff line
@@ -1061,6 +1061,13 @@ static int acpi_lpss_suspend_noirq(struct device *dev)
	int ret;

	if (pdata->dev_desc->resume_from_noirq) {
		/*
		 * The driver's ->suspend_late callback will be invoked by
		 * acpi_lpss_do_suspend_late(), with the assumption that the
		 * driver really wanted to run that code in ->suspend_noirq, but
		 * it could not run after acpi_dev_suspend() and the driver
		 * expected the latter to be called in the "late" phase.
		 */
		ret = acpi_lpss_do_suspend_late(dev);
		if (ret)
			return ret;
@@ -1091,16 +1098,99 @@ static int acpi_lpss_resume_noirq(struct device *dev)
	struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
	int ret;

	ret = acpi_subsys_resume_noirq(dev);
	/* Follow acpi_subsys_resume_noirq(). */
	if (dev_pm_may_skip_resume(dev))
		return 0;

	if (dev_pm_smart_suspend_and_suspended(dev))
		pm_runtime_set_active(dev);

	ret = pm_generic_resume_noirq(dev);
	if (ret)
		return ret;

	if (!dev_pm_may_skip_resume(dev) && pdata->dev_desc->resume_from_noirq)
		ret = acpi_lpss_do_resume_early(dev);
	if (!pdata->dev_desc->resume_from_noirq)
		return 0;

	/*
	 * The driver's ->resume_early callback will be invoked by
	 * acpi_lpss_do_resume_early(), with the assumption that the driver
	 * really wanted to run that code in ->resume_noirq, but it could not
	 * run before acpi_dev_resume() and the driver expected the latter to be
	 * called in the "early" phase.
	 */
	return acpi_lpss_do_resume_early(dev);
}

static int acpi_lpss_do_restore_early(struct device *dev)
{
	int ret = acpi_lpss_resume(dev);

	return ret ? ret : pm_generic_restore_early(dev);
}

static int acpi_lpss_restore_early(struct device *dev)
{
	struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));

	if (pdata->dev_desc->resume_from_noirq)
		return 0;

	return acpi_lpss_do_restore_early(dev);
}

static int acpi_lpss_restore_noirq(struct device *dev)
{
	struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
	int ret;

	ret = pm_generic_restore_noirq(dev);
	if (ret)
		return ret;

	if (!pdata->dev_desc->resume_from_noirq)
		return 0;

	/* This is analogous to what happens in acpi_lpss_resume_noirq(). */
	return acpi_lpss_do_restore_early(dev);
}

static int acpi_lpss_do_poweroff_late(struct device *dev)
{
	int ret = pm_generic_poweroff_late(dev);

	return ret ? ret : acpi_lpss_suspend(dev, device_may_wakeup(dev));
}

static int acpi_lpss_poweroff_late(struct device *dev)
{
	struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));

	if (dev_pm_smart_suspend_and_suspended(dev))
		return 0;

	if (pdata->dev_desc->resume_from_noirq)
		return 0;

	return acpi_lpss_do_poweroff_late(dev);
}

static int acpi_lpss_poweroff_noirq(struct device *dev)
{
	struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));

	if (dev_pm_smart_suspend_and_suspended(dev))
		return 0;

	if (pdata->dev_desc->resume_from_noirq) {
		/* This is analogous to the acpi_lpss_suspend_noirq() case. */
		int ret = acpi_lpss_do_poweroff_late(dev);
		if (ret)
			return ret;
	}

	return pm_generic_poweroff_noirq(dev);
}
#endif /* CONFIG_PM_SLEEP */

static int acpi_lpss_runtime_suspend(struct device *dev)
@@ -1134,14 +1224,11 @@ static struct dev_pm_domain acpi_lpss_pm_domain = {
		.resume_noirq = acpi_lpss_resume_noirq,
		.resume_early = acpi_lpss_resume_early,
		.freeze = acpi_subsys_freeze,
		.freeze_late = acpi_subsys_freeze_late,
		.freeze_noirq = acpi_subsys_freeze_noirq,
		.thaw_noirq = acpi_subsys_thaw_noirq,
		.poweroff = acpi_subsys_suspend,
		.poweroff_late = acpi_lpss_suspend_late,
		.poweroff_noirq = acpi_lpss_suspend_noirq,
		.restore_noirq = acpi_lpss_resume_noirq,
		.restore_early = acpi_lpss_resume_early,
		.poweroff = acpi_subsys_poweroff,
		.poweroff_late = acpi_lpss_poweroff_late,
		.poweroff_noirq = acpi_lpss_poweroff_noirq,
		.restore_noirq = acpi_lpss_restore_noirq,
		.restore_early = acpi_lpss_restore_early,
#endif
		.runtime_suspend = acpi_lpss_runtime_suspend,
		.runtime_resume = acpi_lpss_runtime_resume,
+52 −42
Original line number Diff line number Diff line
@@ -1120,7 +1120,7 @@ EXPORT_SYMBOL_GPL(acpi_subsys_suspend_noirq);
 * acpi_subsys_resume_noirq - Run the device driver's "noirq" resume callback.
 * @dev: Device to handle.
 */
int acpi_subsys_resume_noirq(struct device *dev)
static int acpi_subsys_resume_noirq(struct device *dev)
{
	if (dev_pm_may_skip_resume(dev))
		return 0;
@@ -1135,7 +1135,6 @@ int acpi_subsys_resume_noirq(struct device *dev)

	return pm_generic_resume_noirq(dev);
}
EXPORT_SYMBOL_GPL(acpi_subsys_resume_noirq);

/**
 * acpi_subsys_resume_early - Resume device using ACPI.
@@ -1145,12 +1144,11 @@ EXPORT_SYMBOL_GPL(acpi_subsys_resume_noirq);
 * generic early resume procedure for it during system transition into the
 * working state.
 */
int acpi_subsys_resume_early(struct device *dev)
static int acpi_subsys_resume_early(struct device *dev)
{
	int ret = acpi_dev_resume(dev);
	return ret ? ret : pm_generic_resume_early(dev);
}
EXPORT_SYMBOL_GPL(acpi_subsys_resume_early);

/**
 * acpi_subsys_freeze - Run the device driver's freeze callback.
@@ -1159,12 +1157,13 @@ EXPORT_SYMBOL_GPL(acpi_subsys_resume_early);
int acpi_subsys_freeze(struct device *dev)
{
	/*
	 * This used to be done in acpi_subsys_prepare() for all devices and
	 * some drivers may depend on it, so do it here.  Ideally, however,
	 * runtime-suspended devices should not be touched during freeze/thaw
	 * transitions.
	 * Resume all runtime-suspended devices before creating a snapshot
	 * image of system memory, because the restore kernel generally cannot
	 * be expected to always handle them consistently and they need to be
	 * put into the runtime-active metastate during system resume anyway,
	 * so it is better to ensure that the state saved in the image will be
	 * always consistent with that.
	 */
	if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND))
	pm_runtime_resume(dev);

	return pm_generic_freeze(dev);
@@ -1172,52 +1171,67 @@ int acpi_subsys_freeze(struct device *dev)
EXPORT_SYMBOL_GPL(acpi_subsys_freeze);

/**
 * acpi_subsys_freeze_late - Run the device driver's "late" freeze callback.
 * @dev: Device to handle.
 * acpi_subsys_restore_early - Restore device using ACPI.
 * @dev: Device to restore.
 */
int acpi_subsys_freeze_late(struct device *dev)
int acpi_subsys_restore_early(struct device *dev)
{
	int ret = acpi_dev_resume(dev);
	return ret ? ret : pm_generic_restore_early(dev);
}
EXPORT_SYMBOL_GPL(acpi_subsys_restore_early);

	if (dev_pm_smart_suspend_and_suspended(dev))
		return 0;
/**
 * acpi_subsys_poweroff - Run the device driver's poweroff callback.
 * @dev: Device to handle.
 *
 * Follow PCI and resume devices from runtime suspend before running their
 * system poweroff callbacks, unless the driver can cope with runtime-suspended
 * devices during system suspend and there are no ACPI-specific reasons for
 * resuming them.
 */
int acpi_subsys_poweroff(struct device *dev)
{
	if (!dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) ||
	    acpi_dev_needs_resume(dev, ACPI_COMPANION(dev)))
		pm_runtime_resume(dev);

	return pm_generic_freeze_late(dev);
	return pm_generic_poweroff(dev);
}
EXPORT_SYMBOL_GPL(acpi_subsys_freeze_late);
EXPORT_SYMBOL_GPL(acpi_subsys_poweroff);

/**
 * acpi_subsys_freeze_noirq - Run the device driver's "noirq" freeze callback.
 * acpi_subsys_poweroff_late - Run the device driver's poweroff callback.
 * @dev: Device to handle.
 *
 * Carry out the generic late poweroff procedure for @dev and use ACPI to put
 * it into a low-power state during system transition into a sleep state.
 */
int acpi_subsys_freeze_noirq(struct device *dev)
static int acpi_subsys_poweroff_late(struct device *dev)
{
	int ret;

	if (dev_pm_smart_suspend_and_suspended(dev))
		return 0;

	return pm_generic_freeze_noirq(dev);
	ret = pm_generic_poweroff_late(dev);
	if (ret)
		return ret;

	return acpi_dev_suspend(dev, device_may_wakeup(dev));
}
EXPORT_SYMBOL_GPL(acpi_subsys_freeze_noirq);

/**
 * acpi_subsys_thaw_noirq - Run the device driver's "noirq" thaw callback.
 * @dev: Device to handle.
 * acpi_subsys_poweroff_noirq - Run the driver's "noirq" poweroff callback.
 * @dev: Device to suspend.
 */
int acpi_subsys_thaw_noirq(struct device *dev)
static int acpi_subsys_poweroff_noirq(struct device *dev)
{
	/*
	 * If the device is in runtime suspend, the "thaw" code may not work
	 * correctly with it, so skip the driver callback and make the PM core
	 * skip all of the subsequent "thaw" callbacks for the device.
	 */
	if (dev_pm_smart_suspend_and_suspended(dev)) {
		dev_pm_skip_next_resume_phases(dev);
	if (dev_pm_smart_suspend_and_suspended(dev))
		return 0;
	}

	return pm_generic_thaw_noirq(dev);
	return pm_generic_poweroff_noirq(dev);
}
EXPORT_SYMBOL_GPL(acpi_subsys_thaw_noirq);
#endif /* CONFIG_PM_SLEEP */

static struct dev_pm_domain acpi_general_pm_domain = {
@@ -1233,14 +1247,10 @@ static struct dev_pm_domain acpi_general_pm_domain = {
		.resume_noirq = acpi_subsys_resume_noirq,
		.resume_early = acpi_subsys_resume_early,
		.freeze = acpi_subsys_freeze,
		.freeze_late = acpi_subsys_freeze_late,
		.freeze_noirq = acpi_subsys_freeze_noirq,
		.thaw_noirq = acpi_subsys_thaw_noirq,
		.poweroff = acpi_subsys_suspend,
		.poweroff_late = acpi_subsys_suspend_late,
		.poweroff_noirq = acpi_subsys_suspend_noirq,
		.restore_noirq = acpi_subsys_resume_noirq,
		.restore_early = acpi_subsys_resume_early,
		.poweroff = acpi_subsys_poweroff,
		.poweroff_late = acpi_subsys_poweroff_late,
		.poweroff_noirq = acpi_subsys_poweroff_noirq,
		.restore_early = acpi_subsys_restore_early,
#endif
	},
};
+14 −22
Original line number Diff line number Diff line
@@ -529,21 +529,6 @@ static void dpm_watchdog_clear(struct dpm_watchdog *wd)

/*------------------------- Resume routines -------------------------*/

/**
 * dev_pm_skip_next_resume_phases - Skip next system resume phases for device.
 * @dev: Target device.
 *
 * Make the core skip the "early resume" and "resume" phases for @dev.
 *
 * This function can be called by middle-layer code during the "noirq" phase of
 * system resume if necessary, but not by device drivers.
 */
void dev_pm_skip_next_resume_phases(struct device *dev)
{
	dev->power.is_late_suspended = false;
	dev->power.is_suspended = false;
}

/**
 * suspend_event - Return a "suspend" message for given "resume" one.
 * @resume_msg: PM message representing a system-wide resume transition.
@@ -681,6 +666,9 @@ static int device_resume_noirq(struct device *dev, pm_message_t state, bool asyn
	dev->power.is_noirq_suspended = false;

	if (skip_resume) {
		/* Make the next phases of resume skip the device. */
		dev->power.is_late_suspended = false;
		dev->power.is_suspended = false;
		/*
		 * The device is going to be left in suspend, but it might not
		 * have been in runtime suspend before the system suspended, so
@@ -689,7 +677,6 @@ static int device_resume_noirq(struct device *dev, pm_message_t state, bool asyn
		 * device again.
		 */
		pm_runtime_set_suspended(dev);
		dev_pm_skip_next_resume_phases(dev);
	}

Out:
@@ -1631,17 +1618,20 @@ int dpm_suspend_late(pm_message_t state)
 */
int dpm_suspend_end(pm_message_t state)
{
	int error = dpm_suspend_late(state);
	ktime_t starttime = ktime_get();
	int error;

	error = dpm_suspend_late(state);
	if (error)
		return error;
		goto out;

	error = dpm_suspend_noirq(state);
	if (error) {
	if (error)
		dpm_resume_early(resume_event(state));
		return error;
	}

	return 0;
out:
	dpm_show_time(starttime, state, error, "end");
	return error;
}
EXPORT_SYMBOL_GPL(dpm_suspend_end);

@@ -2034,6 +2024,7 @@ int dpm_prepare(pm_message_t state)
 */
int dpm_suspend_start(pm_message_t state)
{
	ktime_t starttime = ktime_get();
	int error;

	error = dpm_prepare(state);
@@ -2042,6 +2033,7 @@ int dpm_suspend_start(pm_message_t state)
		dpm_save_failed_step(SUSPEND_PREPARE);
	} else
		error = dpm_suspend(state);
	dpm_show_time(starttime, state, error, "start");
	return error;
}
EXPORT_SYMBOL_GPL(dpm_suspend_start);
Loading