Commit 05d658b5 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branch 'pm-sleep'

* pm-sleep:
  freezer: Fix typo in freezable_schedule_timeout() comment
  PM / s2idle: Clear the events_check_enabled flag
  PM / sleep: Remove pm_complete_with_resume_check()
  PM: ARM: locomo: Drop suspend and resume bus type callbacks
  PM: Use a more common logging style
  PM: Document rules on using pm_runtime_resume() in system suspend callbacks
parents 794c3355 2dd9789c
...@@ -328,7 +328,10 @@ the phases are: ``prepare``, ``suspend``, ``suspend_late``, ``suspend_noirq``. ...@@ -328,7 +328,10 @@ the phases are: ``prepare``, ``suspend``, ``suspend_late``, ``suspend_noirq``.
After the ``->prepare`` callback method returns, no new children may be After the ``->prepare`` callback method returns, no new children may be
registered below the device. The method may also prepare the device or registered below the device. The method may also prepare the device or
driver in some way for the upcoming system power transition, but it driver in some way for the upcoming system power transition, but it
should not put the device into a low-power state. should not put the device into a low-power state. Moreover, if the
device supports runtime power management, the ``->prepare`` callback
method must not update its state in case it is necessary to resume it
from runtime suspend later on.
For devices supporting runtime power management, the return value of the For devices supporting runtime power management, the return value of the
prepare callback can be used to indicate to the PM core that it may prepare callback can be used to indicate to the PM core that it may
...@@ -356,6 +359,16 @@ the phases are: ``prepare``, ``suspend``, ``suspend_late``, ``suspend_noirq``. ...@@ -356,6 +359,16 @@ the phases are: ``prepare``, ``suspend``, ``suspend_late``, ``suspend_noirq``.
the appropriate low-power state, depending on the bus type the device is the appropriate low-power state, depending on the bus type the device is
on, and they may enable wakeup events. on, and they may enable wakeup events.
However, for devices supporting runtime power management, the
``->suspend`` methods provided by subsystems (bus types and PM domains
in particular) must follow an additional rule regarding what can be done
to the devices before their drivers' ``->suspend`` methods are called.
Namely, they can only resume the devices from runtime suspend by
calling :c:func:`pm_runtime_resume` for them, if that is necessary, and
they must not update the state of the devices in any other way at that
time (in case the drivers need to resume the devices from runtime
suspend in their ``->suspend`` methods).
3. For a number of devices it is convenient to split suspend into the 3. For a number of devices it is convenient to split suspend into the
"quiesce device" and "save device state" phases, in which cases "quiesce device" and "save device state" phases, in which cases
``suspend_late`` is meant to do the latter. It is always executed after ``suspend_late`` is meant to do the latter. It is always executed after
...@@ -729,6 +742,16 @@ state temporarily, for example so that its system wakeup capability can be ...@@ -729,6 +742,16 @@ state temporarily, for example so that its system wakeup capability can be
disabled. This all depends on the hardware and the design of the subsystem and disabled. This all depends on the hardware and the design of the subsystem and
device driver in question. device driver in question.
If it is necessary to resume a device from runtime suspend during a system-wide
transition into a sleep state, that can be done by calling
:c:func:`pm_runtime_resume` for it from the ``->suspend`` callback (or its
couterpart for transitions related to hibernation) of either the device's driver
or a subsystem responsible for it (for example, a bus type or a PM domain).
That is guaranteed to work by the requirement that subsystems must not change
the state of devices (possibly except for resuming them from runtime suspend)
from their ``->prepare`` and ``->suspend`` callbacks (or equivalent) *before*
invoking device drivers' ``->suspend`` callbacks (or equivalent).
During system-wide resume from a sleep state it's easiest to put devices into During system-wide resume from a sleep state it's easiest to put devices into
the full-power state, as explained in :file:`Documentation/power/runtime_pm.txt`. the full-power state, as explained in :file:`Documentation/power/runtime_pm.txt`.
Refer to that document for more information regarding this particular issue as Refer to that document for more information regarding this particular issue as
......
...@@ -826,28 +826,6 @@ static int locomo_match(struct device *_dev, struct device_driver *_drv) ...@@ -826,28 +826,6 @@ static int locomo_match(struct device *_dev, struct device_driver *_drv)
return dev->devid == drv->devid; return dev->devid == drv->devid;
} }
static int locomo_bus_suspend(struct device *dev, pm_message_t state)
{
struct locomo_dev *ldev = LOCOMO_DEV(dev);
struct locomo_driver *drv = LOCOMO_DRV(dev->driver);
int ret = 0;
if (drv && drv->suspend)
ret = drv->suspend(ldev, state);
return ret;
}
static int locomo_bus_resume(struct device *dev)
{
struct locomo_dev *ldev = LOCOMO_DEV(dev);
struct locomo_driver *drv = LOCOMO_DRV(dev->driver);
int ret = 0;
if (drv && drv->resume)
ret = drv->resume(ldev);
return ret;
}
static int locomo_bus_probe(struct device *dev) static int locomo_bus_probe(struct device *dev)
{ {
struct locomo_dev *ldev = LOCOMO_DEV(dev); struct locomo_dev *ldev = LOCOMO_DEV(dev);
...@@ -875,8 +853,6 @@ struct bus_type locomo_bus_type = { ...@@ -875,8 +853,6 @@ struct bus_type locomo_bus_type = {
.match = locomo_match, .match = locomo_match,
.probe = locomo_bus_probe, .probe = locomo_bus_probe,
.remove = locomo_bus_remove, .remove = locomo_bus_remove,
.suspend = locomo_bus_suspend,
.resume = locomo_bus_resume,
}; };
int locomo_driver_register(struct locomo_driver *driver) int locomo_driver_register(struct locomo_driver *driver)
......
...@@ -189,8 +189,6 @@ struct locomo_driver { ...@@ -189,8 +189,6 @@ struct locomo_driver {
unsigned int devid; unsigned int devid;
int (*probe)(struct locomo_dev *); int (*probe)(struct locomo_dev *);
int (*remove)(struct locomo_dev *); int (*remove)(struct locomo_dev *);
int (*suspend)(struct locomo_dev *, pm_message_t);
int (*resume)(struct locomo_dev *);
}; };
#define LOCOMO_DRV(_d) container_of((_d), struct locomo_driver, drv) #define LOCOMO_DRV(_d) container_of((_d), struct locomo_driver, drv)
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/export.h> #include <linux/export.h>
#include <linux/suspend.h>
#ifdef CONFIG_PM #ifdef CONFIG_PM
/** /**
...@@ -298,26 +297,4 @@ void pm_generic_complete(struct device *dev) ...@@ -298,26 +297,4 @@ void pm_generic_complete(struct device *dev)
if (drv && drv->pm && drv->pm->complete) if (drv && drv->pm && drv->pm->complete)
drv->pm->complete(dev); drv->pm->complete(dev);
} }
/**
* pm_complete_with_resume_check - Complete a device power transition.
* @dev: Device to handle.
*
* Complete a device power transition during a system-wide power transition and
* optionally schedule a runtime resume of the device if the system resume in
* progress has been initated by the platform firmware and the device had its
* power.direct_complete flag set.
*/
void pm_complete_with_resume_check(struct device *dev)
{
pm_generic_complete(dev);
/*
* If the device had been runtime-suspended before the system went into
* the sleep state it is going out of and it has never been resumed till
* now, resume it in case the firmware powered it up.
*/
if (dev->power.direct_complete && pm_resume_via_firmware())
pm_request_resume(dev);
}
EXPORT_SYMBOL_GPL(pm_complete_with_resume_check);
#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM_SLEEP */
...@@ -182,7 +182,7 @@ static inline void freezable_schedule_unsafe(void) ...@@ -182,7 +182,7 @@ static inline void freezable_schedule_unsafe(void)
} }
/* /*
* Like freezable_schedule_timeout(), but should not block the freezer. Do not * Like schedule_timeout(), but should not block the freezer. Do not
* call this with locks held. * call this with locks held.
*/ */
static inline long freezable_schedule_timeout(long timeout) static inline long freezable_schedule_timeout(long timeout)
......
...@@ -736,7 +736,6 @@ extern int pm_generic_poweroff_noirq(struct device *dev); ...@@ -736,7 +736,6 @@ extern int pm_generic_poweroff_noirq(struct device *dev);
extern int pm_generic_poweroff_late(struct device *dev); extern int pm_generic_poweroff_late(struct device *dev);
extern int pm_generic_poweroff(struct device *dev); extern int pm_generic_poweroff(struct device *dev);
extern void pm_generic_complete(struct device *dev); extern void pm_generic_complete(struct device *dev);
extern void pm_complete_with_resume_check(struct device *dev);
#else /* !CONFIG_PM_SLEEP */ #else /* !CONFIG_PM_SLEEP */
......
...@@ -701,8 +701,8 @@ static int __init pm_qos_power_init(void) ...@@ -701,8 +701,8 @@ static int __init pm_qos_power_init(void)
for (i = PM_QOS_CPU_DMA_LATENCY; i < PM_QOS_NUM_CLASSES; i++) { for (i = PM_QOS_CPU_DMA_LATENCY; i < PM_QOS_NUM_CLASSES; i++) {
ret = register_pm_qos_misc(pm_qos_array[i], d); ret = register_pm_qos_misc(pm_qos_array[i], d);
if (ret < 0) { if (ret < 0) {
printk(KERN_ERR "pm_qos_param: %s setup failed\n", pr_err("%s: %s setup failed\n",
pm_qos_array[i]->name); __func__, pm_qos_array[i]->name);
return ret; return ret;
} }
} }
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
* *
*/ */
#define pr_fmt(fmt) "PM: " fmt
#include <linux/version.h> #include <linux/version.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mm.h> #include <linux/mm.h>
...@@ -967,7 +969,7 @@ void __init __register_nosave_region(unsigned long start_pfn, ...@@ -967,7 +969,7 @@ void __init __register_nosave_region(unsigned long start_pfn,
region->end_pfn = end_pfn; region->end_pfn = end_pfn;
list_add_tail(&region->list, &nosave_regions); list_add_tail(&region->list, &nosave_regions);
Report: Report:
printk(KERN_INFO "PM: Registered nosave memory: [mem %#010llx-%#010llx]\n", pr_info("Registered nosave memory: [mem %#010llx-%#010llx]\n",
(unsigned long long) start_pfn << PAGE_SHIFT, (unsigned long long) start_pfn << PAGE_SHIFT,
((unsigned long long) end_pfn << PAGE_SHIFT) - 1); ((unsigned long long) end_pfn << PAGE_SHIFT) - 1);
} }
...@@ -1039,7 +1041,7 @@ static void mark_nosave_pages(struct memory_bitmap *bm) ...@@ -1039,7 +1041,7 @@ static void mark_nosave_pages(struct memory_bitmap *bm)
list_for_each_entry(region, &nosave_regions, list) { list_for_each_entry(region, &nosave_regions, list) {
unsigned long pfn; unsigned long pfn;
pr_debug("PM: Marking nosave pages: [mem %#010llx-%#010llx]\n", pr_debug("Marking nosave pages: [mem %#010llx-%#010llx]\n",
(unsigned long long) region->start_pfn << PAGE_SHIFT, (unsigned long long) region->start_pfn << PAGE_SHIFT,
((unsigned long long) region->end_pfn << PAGE_SHIFT) ((unsigned long long) region->end_pfn << PAGE_SHIFT)
- 1); - 1);
...@@ -1095,7 +1097,7 @@ int create_basic_memory_bitmaps(void) ...@@ -1095,7 +1097,7 @@ int create_basic_memory_bitmaps(void)
free_pages_map = bm2; free_pages_map = bm2;
mark_nosave_pages(forbidden_pages_map); mark_nosave_pages(forbidden_pages_map);
pr_debug("PM: Basic memory bitmaps created\n"); pr_debug("Basic memory bitmaps created\n");
return 0; return 0;
...@@ -1131,7 +1133,7 @@ void free_basic_memory_bitmaps(void) ...@@ -1131,7 +1133,7 @@ void free_basic_memory_bitmaps(void)
memory_bm_free(bm2, PG_UNSAFE_CLEAR); memory_bm_free(bm2, PG_UNSAFE_CLEAR);
kfree(bm2); kfree(bm2);
pr_debug("PM: Basic memory bitmaps freed\n"); pr_debug("Basic memory bitmaps freed\n");
} }
void clear_free_pages(void) void clear_free_pages(void)
...@@ -1152,7 +1154,7 @@ void clear_free_pages(void) ...@@ -1152,7 +1154,7 @@ void clear_free_pages(void)
pfn = memory_bm_next_pfn(bm); pfn = memory_bm_next_pfn(bm);
} }
memory_bm_position_reset(bm); memory_bm_position_reset(bm);
pr_info("PM: free pages cleared after restore\n"); pr_info("free pages cleared after restore\n");
#endif /* PAGE_POISONING_ZERO */ #endif /* PAGE_POISONING_ZERO */
} }
...@@ -1690,7 +1692,7 @@ int hibernate_preallocate_memory(void) ...@@ -1690,7 +1692,7 @@ int hibernate_preallocate_memory(void)
ktime_t start, stop; ktime_t start, stop;
int error; int error;
printk(KERN_INFO "PM: Preallocating image memory... "); pr_info("Preallocating image memory... ");
start = ktime_get(); start = ktime_get();
error = memory_bm_create(&orig_bm, GFP_IMAGE, PG_ANY); error = memory_bm_create(&orig_bm, GFP_IMAGE, PG_ANY);
...@@ -1821,13 +1823,13 @@ int hibernate_preallocate_memory(void) ...@@ -1821,13 +1823,13 @@ int hibernate_preallocate_memory(void)
out: out:
stop = ktime_get(); stop = ktime_get();
printk(KERN_CONT "done (allocated %lu pages)\n", pages); pr_cont("done (allocated %lu pages)\n", pages);
swsusp_show_speed(start, stop, pages, "Allocated"); swsusp_show_speed(start, stop, pages, "Allocated");
return 0; return 0;
err_out: err_out:
printk(KERN_CONT "\n"); pr_cont("\n");
swsusp_free(); swsusp_free();
return -ENOMEM; return -ENOMEM;
} }
...@@ -1867,8 +1869,8 @@ static int enough_free_mem(unsigned int nr_pages, unsigned int nr_highmem) ...@@ -1867,8 +1869,8 @@ static int enough_free_mem(unsigned int nr_pages, unsigned int nr_highmem)
free += zone_page_state(zone, NR_FREE_PAGES); free += zone_page_state(zone, NR_FREE_PAGES);
nr_pages += count_pages_for_highmem(nr_highmem); nr_pages += count_pages_for_highmem(nr_highmem);
pr_debug("PM: Normal pages needed: %u + %u, available pages: %u\n", pr_debug("Normal pages needed: %u + %u, available pages: %u\n",
nr_pages, PAGES_FOR_IO, free); nr_pages, PAGES_FOR_IO, free);
return free > nr_pages + PAGES_FOR_IO; return free > nr_pages + PAGES_FOR_IO;
} }
...@@ -1961,20 +1963,20 @@ asmlinkage __visible int swsusp_save(void) ...@@ -1961,20 +1963,20 @@ asmlinkage __visible int swsusp_save(void)
{ {
unsigned int nr_pages, nr_highmem; unsigned int nr_pages, nr_highmem;
printk(KERN_INFO "PM: Creating hibernation image:\n"); pr_info("Creating hibernation image:\n");
drain_local_pages(NULL); drain_local_pages(NULL);
nr_pages = count_data_pages(); nr_pages = count_data_pages();
nr_highmem = count_highmem_pages(); nr_highmem = count_highmem_pages();
printk(KERN_INFO "PM: Need to copy %u pages\n", nr_pages + nr_highmem); pr_info("Need to copy %u pages\n", nr_pages + nr_highmem);
if (!enough_free_mem(nr_pages, nr_highmem)) { if (!enough_free_mem(nr_pages, nr_highmem)) {
printk(KERN_ERR "PM: Not enough free memory\n"); pr_err("Not enough free memory\n");
return -ENOMEM; return -ENOMEM;
} }
if (swsusp_alloc(&copy_bm, nr_pages, nr_highmem)) { if (swsusp_alloc(&copy_bm, nr_pages, nr_highmem)) {
printk(KERN_ERR "PM: Memory allocation failed\n"); pr_err("Memory allocation failed\n");
return -ENOMEM; return -ENOMEM;
} }
...@@ -1995,8 +1997,7 @@ asmlinkage __visible int swsusp_save(void) ...@@ -1995,8 +1997,7 @@ asmlinkage __visible int swsusp_save(void)
nr_copy_pages = nr_pages; nr_copy_pages = nr_pages;
nr_meta_pages = DIV_ROUND_UP(nr_pages * sizeof(long), PAGE_SIZE); nr_meta_pages = DIV_ROUND_UP(nr_pages * sizeof(long), PAGE_SIZE);
printk(KERN_INFO "PM: Hibernation image created (%d pages copied)\n", pr_info("Hibernation image created (%d pages copied)\n", nr_pages);
nr_pages);
return 0; return 0;
} }
...@@ -2170,7 +2171,7 @@ static int check_header(struct swsusp_info *info) ...@@ -2170,7 +2171,7 @@ static int check_header(struct swsusp_info *info)
if (!reason && info->num_physpages != get_num_physpages()) if (!reason && info->num_physpages != get_num_physpages())
reason = "memory size"; reason = "memory size";
if (reason) { if (reason) {
printk(KERN_ERR "PM: Image mismatch: %s\n", reason); pr_err("Image mismatch: %s\n", reason);
return -EPERM; return -EPERM;
} }
return 0; return 0;
......
...@@ -437,7 +437,6 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) ...@@ -437,7 +437,6 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
error = suspend_ops->enter(state); error = suspend_ops->enter(state);
trace_suspend_resume(TPS("machine_suspend"), trace_suspend_resume(TPS("machine_suspend"),
state, false); state, false);
events_check_enabled = false;
} else if (*wakeup) { } else if (*wakeup) {
error = -EBUSY; error = -EBUSY;
} }
...@@ -582,6 +581,7 @@ static int enter_state(suspend_state_t state) ...@@ -582,6 +581,7 @@ static int enter_state(suspend_state_t state)
pm_restore_gfp_mask(); pm_restore_gfp_mask();
Finish: Finish:
events_check_enabled = false;
pm_pr_dbg("Finishing wakeup.\n"); pm_pr_dbg("Finishing wakeup.\n");
suspend_finish(); suspend_finish();
Unlock: Unlock:
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment