Power Management Notifiers

Power-management notifiers are the kernel-internal broadcast that lets any subsystem react to a system-wide PM transition — suspend, resume, hibernate, restore — at a point where the system is still fully functional, before user tasks are frozen and devices are quiesced. A subsystem registers a callback with register_pm_notifier(); when the suspend or hibernate core is about to begin, it calls pm_notifier_call_chain() (or its rollback-capable cousin pm_notifier_call_chain_robust()), which walks every registered callback passing one of six event constants — PM_SUSPEND_PREPARE, PM_POST_SUSPEND, PM_HIBERNATION_PREPARE, PM_POST_HIBERNATION, PM_RESTORE_PREPARE, PM_POST_RESTORE. The mechanism exists precisely because a driver’s ->suspend() / ->prepare() callbacks run too late for some work: by then memory allocation is restricted and (for resume) user processes are frozen, so anything that needs a fully-working system — loading firmware, allocating large buffers, stopping a workqueue — must happen at the notifier point instead (notifiers.rst). The implementation lives in kernel/power/main.c, verified here against Linux 6.12 LTS (released 2024-11-17).

The single idea to take away: notifiers fire at the earliest point of a system PM transition — before the freezer runs — which is the only window where a subsystem can still do work that requires the whole system to be alive. A *_PREPARE notifier returning an error aborts the entire transition, so it is also a veto.

Mental Model: A Doorbell Rung Before the System Goes to Sleep

Think of the PM notifier chain as a doorbell the suspend/hibernate core rings on its way into a transition (and again on its way out). Every subsystem that cares — RCU, cpufreq’s frequency-invariance machinery, certain drivers, virtualization guests — has hung a callback on the doorbell. The core rings it once with a *_PREPARE event at the very start (system fully functional, no tasks frozen yet) and once with a POST_* event at the very end (after everything has been undone). This is fundamentally different from the per-device dev_pm_ops callbacks: those run per device, in dependency order, after the freezer; the notifier runs once, system-wide, before the freezer. It is also different from runtime PM, which is entirely per-device and never involves this chain.

flowchart TB
  START["User requests suspend<br/>(echo mem > /sys/power/state)"]
  PREP["suspend_prepare()"]
  NOTIFY["pm_notifier_call_chain_robust(<br/>PM_SUSPEND_PREPARE, PM_POST_SUSPEND)"]
  CHK{"any notifier<br/>returned error?"}
  ABORT["roll back already-called notifiers<br/>with PM_POST_SUSPEND,<br/>abort transition"]
  FREEZE["suspend_freeze_processes()<br/>(freezer runs HERE)"]
  DEV["device suspend phases<br/>(dev_pm_ops callbacks)"]
  SLEEP["enter sleep state"]
  RESUME["resume devices + thaw tasks"]
  POST["pm_notifier_call_chain(PM_POST_SUSPEND)"]
  START --> PREP --> NOTIFY --> CHK
  CHK -->|"yes"| ABORT
  CHK -->|"no"| FREEZE --> DEV --> SLEEP --> RESUME --> POST

Where the PM notifier chain fires in the suspend flow. What it shows: PM_SUSPEND_PREPARE is broadcast inside suspend_prepare(), before suspend_freeze_processes() runs — so notifiers execute while the system is fully alive; PM_POST_SUSPEND is broadcast at the end, after tasks are thawed. The insight to take: an error from any *_PREPARE notifier aborts the whole transition (and the already-notified callbacks are rolled back), making the notifier both a reaction hook and a veto.

The Implementation: One Blocking Notifier Chain

The entire mechanism is a single global notifier chain declared in kernel/power/main.c:

static BLOCKING_NOTIFIER_HEAD(pm_chain_head);
 
int register_pm_notifier(struct notifier_block *nb)
{
    return blocking_notifier_chain_register(&pm_chain_head, nb);
}
EXPORT_SYMBOL_GPL(register_pm_notifier);
 
int unregister_pm_notifier(struct notifier_block *nb)
{
    return blocking_notifier_chain_unregister(&pm_chain_head, nb);
}
EXPORT_SYMBOL_GPL(unregister_pm_notifier);

BLOCKING_NOTIFIER_HEAD matters: it makes pm_chain_head a blocking notifier chain, protected by an rw_semaphore, which means notifier callbacks may sleep (notifier.h, v6.12). That is exactly what a notifier needs — at the *_PREPARE point, allocating memory, loading firmware, or flushing a workqueue all sleep, and they are allowed to because the system is still fully running with interrupts and scheduling enabled. (Contrast an atomic notifier chain, used where callbacks run in atomic context and must not sleep.)

A struct notifier_block is three fields (notifier.h, v6.12):

struct notifier_block {
    notifier_fn_t notifier_call;          /* int (*)(struct notifier_block *, unsigned long action, void *data) */
    struct notifier_block __rcu *next;    /* the chain links itself */
    int priority;                         /* higher priority runs earlier */
};

priority orders the chain: a notifier registered with a higher priority is called before lower-priority ones for the up events and (by the rollback design below) after them for the recovery events. Most PM notifiers use priority 0.

For permanent (never-unregistered) notifiers there is a convenience macro that hides the boilerplate of declaring the notifier_block and registering it (suspend.h, v6.12):

#define pm_notifier(fn, pri) {                          \
    static struct notifier_block fn##_nb =              \
        { .notifier_call = fn, .priority = pri };       \
    register_pm_notifier(&fn##_nb);                     \
}

The Six Events and Exactly When They Fire

The event constants are defined in include/linux/suspend.h:

#define PM_HIBERNATION_PREPARE  0x0001 /* Going to hibernate */
#define PM_POST_HIBERNATION     0x0002 /* Hibernation finished */
#define PM_SUSPEND_PREPARE      0x0003 /* Going to suspend the system */
#define PM_POST_SUSPEND         0x0004 /* Suspend finished */
#define PM_RESTORE_PREPARE      0x0005 /* Going to restore a saved image */
#define PM_POST_RESTORE         0x0006 /* Restore failed */

They pair up: each *_PREPARE has a matching POST_*. The crucial fact — verifiable in the call sites — is that every *_PREPARE fires before tasks are frozen.

Suspend (suspend-to-RAM / suspend-to-idle). In suspend_prepare() (kernel/power/suspend.c, v6.12):

static int suspend_prepare(suspend_state_t state)
{
    ...
    pm_prepare_console();
    error = pm_notifier_call_chain_robust(PM_SUSPEND_PREPARE, PM_POST_SUSPEND);
    if (error)
        goto Restore;                       /* notifier vetoed the suspend */
 
    error = suspend_freeze_processes();      /* <-- freezer runs AFTER notifiers */
    ...
}

The ordering is unambiguous: PM_SUSPEND_PREPARE is broadcast, and only if it succeeds does suspend_freeze_processes() run. The matching PM_POST_SUSPEND fires at the end of the transition in suspend_finish(), after tasks are thawed:

static void suspend_finish(void)
{
    suspend_thaw_processes();
    pm_notifier_call_chain(PM_POST_SUSPEND);
    pm_restore_console();
}

Hibernation (suspend-to-disk). Same pattern in hibernate() (kernel/power/hibernate.c, v6.12):

pm_prepare_console();
error = pm_notifier_call_chain_robust(PM_HIBERNATION_PREPARE, PM_POST_HIBERNATION);
if (error)
    goto Restore;
 
ksys_sync_helper();
error = freeze_processes();                  /* <-- freezer AFTER notifiers */

PM_POST_HIBERNATION fires at the end (pm_notifier_call_chain(PM_POST_HIBERNATION) on the exit path). The documented difference between PM_HIBERNATION_PREPARE and PM_SUSPEND_PREPARE is that for hibernation “additional work is done between the notifiers and the invocation of PM callbacks” (notifiers.rst) — specifically the memory-image snapshot — so hibernation notifiers must be even more careful about memory.

Restore (resuming from a hibernation image). The restore path is the asymmetric one. When the kernel boots and finds a hibernation image to load, software_resume() broadcasts PM_RESTORE_PREPARE before freezing tasks (hibernate.c, v6.12):

error = pm_notifier_call_chain_robust(PM_RESTORE_PREPARE, PM_POST_RESTORE);
if (error)
    goto Restore;
error = freeze_processes();
...
error = load_image_and_restore();
thaw_processes();
Finish:
    pm_notifier_call_chain(PM_POST_RESTORE);

PM_RESTORE_PREPARE means “the currently running kernel is about to be replaced by the saved image” — a subsystem may need to release resources that would conflict with the restored kernel. PM_POST_RESTORE is documented as firing when “an error occurred during restore” — on a successful restore the running kernel is discarded and execution jumps into the saved image, which resumes via its own suspend path (it sees PM_POST_HIBERNATION, not PM_POST_RESTORE). So PM_POST_RESTORE is effectively the restore-failure cleanup event.

Why an Error Aborts the Transition: the Robust Chain

The *_PREPARE events use pm_notifier_call_chain_robust(), which is the key to the “notifier returning an error aborts the transition” behavior and to clean rollback. Its definition (kernel/power/main.c, v6.12):

int pm_notifier_call_chain_robust(unsigned long val_up, unsigned long val_down)
{
    int ret = blocking_notifier_call_chain_robust(&pm_chain_head, val_up, val_down, NULL);
    return notifier_to_errno(ret);
}

It is passed both the up event (PM_SUSPEND_PREPARE) and the down event (PM_POST_SUSPEND). The underlying notifier_call_chain_robust() (kernel/notifier.c, v6.12) does:

static int notifier_call_chain_robust(struct notifier_block **nl,
        unsigned long val_up, unsigned long val_down, void *v)
{
    int ret, nr = 0;
    ret = notifier_call_chain(nl, val_up, v, -1, &nr);   /* call with up event */
    if (ret & NOTIFY_STOP_MASK)                          /* a callback said "stop" */
        notifier_call_chain(nl, val_down, v, nr-1, NULL);/* roll back the ones that ran */
    return ret;
}

Reading this carefully: it calls the chain with val_up (e.g. PM_SUSPEND_PREPARE), counting how many callbacks ran in nr. The inner notifier_call_chain() stops early the moment a callback returns a value with NOTIFY_STOP_MASK set (notifier.c, v6.12):

ret = nb->notifier_call(nb, val, v);
if (ret & NOTIFY_STOP_MASK)
    break;

If that happened, notifier_call_chain_robust() immediately replays the chain with val_down (PM_POST_SUSPEND) for the nr-1 callbacks that had already succeeded — undoing their preparation. The failing callback is not rolled back (it is responsible for cleaning up its own partial work before returning the error). This is why prepare/post events come in pairs: the post event is the rollback half. The return value is run through notifier_to_errno(), which decodes the NOTIFY_* code back into a negative errno that suspend_prepare()/hibernate() propagate, aborting the transition.

The NOTIFY_* return codes a callback can use (notifier.h, v6.12):

#define NOTIFY_DONE      0x0000              /* Don't care */
#define NOTIFY_OK        0x0001              /* Suits me */
#define NOTIFY_STOP_MASK 0x8000              /* Don't call further */
#define NOTIFY_BAD       (NOTIFY_STOP_MASK | 0x0002)  /* Bad/veto this action */

A PM notifier that wants to abort a suspend returns notifier_from_errno(-ESOMETHING) (which sets NOTIFY_STOP_MASK) or NOTIFY_BAD; a notifier that is happy returns NOTIFY_OK or NOTIFY_DONE. The notifier_to_errno() helper maps the encoded value back: NOTIFY_BAD (==NOTIFY_STOP_MASK | 0x0002) decodes to -EPERM, while a notifier_from_errno(-ENOMEM) round-trips back to -ENOMEM.

A Realistic Consumer: RCU Expediting Grace Periods

The in-tree RCU subsystem is a clean, real example of a PM notifier reacting to a system-wide transition. It registers a notifier at boot with the pm_notifier() macro and uses it to make suspend and hibernation faster (kernel/rcu/tree.c, v6.12):

static int rcu_pm_notify(struct notifier_block *self,
                         unsigned long action, void *hcpu)
{
    switch (action) {
    case PM_HIBERNATION_PREPARE:
    case PM_SUSPEND_PREPARE:
        rcu_async_hurry();
        rcu_expedite_gp();          /* force expedited grace periods */
        break;
    case PM_POST_HIBERNATION:
    case PM_POST_SUSPEND:
        rcu_unexpedite_gp();        /* undo it */
        rcu_async_relax();
        break;
    default:
        break;
    }
    return NOTIFY_OK;
}
/* ... registered once, at RCU init: */
pm_notifier(rcu_pm_notify, 0);

The logic is instructive on three counts. First, it demonstrates the symmetric pairing: whatever it does on *_PREPARE (switch RCU to expedited grace periods so the many synchronization points during the suspend sweep complete quickly rather than waiting for normal grace periods), it undoes on the matching POST_*. Second, it treats PM_HIBERNATION_PREPARE and PM_SUSPEND_PREPARE identically — many notifiers don’t care which kind of system sleep is happening, only that one is. Third, it always returns NOTIFY_OK — RCU never vetoes a transition; it merely tunes itself. This is the common case: most PM notifiers are reactive, not vetoing.

The classic vetoing use case from the documentation is the inverse: a subsystem that cannot allow hibernation right now (e.g. it holds a resource that can’t survive the memory snapshot) returns an error from its PM_HIBERNATION_PREPARE handler, and the robust chain aborts the hibernation cleanly. The other canonical pattern is preparatory allocation: a driver that must request_firmware() after resume cannot do so from its ->resume() callback (user-space, which the firmware loader needs, is frozen there), so it loads the firmware into memory at PM_HIBERNATION_PREPARE / PM_SUSPEND_PREPARE time — while the system is fully functional — and uploads it from memory in ->resume() (notifiers.rst). Whatever it allocated for the *_PREPARE event it frees on the matching POST_* event.

Failure Modes and Common Misunderstandings

A notifier that sleeps too long stalls every suspend. Because the chain is blocking and serial, a slow notifier (e.g. one that flushes a huge workqueue or does network I/O) adds its latency to every suspend and hibernate. There is no per-notifier timeout; a hung notifier hangs the whole transition. Diagnose with the suspend_resume ftrace events bracketing the prepare phase.

Forgetting the rollback half. A notifier that allocates a resource on PM_SUSPEND_PREPARE but only frees it on PM_POST_SUSPEND will leak if a later notifier in the chain vetoes the suspend — because in that case the robust chain calls the down event (PM_POST_SUSPEND) for the already-run notifiers, which is exactly why you must free on the POST event and not, say, on a successful-resume assumption. Conversely, if you free only on a deeper transition event you’ll never see, you leak. The rule: do/undo strictly in the *_PREPARE / POST_* pair.

Assuming PM_POST_RESTORE always fires on a successful restore. It does not. A successful hibernation restore jumps into the saved image and the image’s kernel context resumes via PM_POST_HIBERNATION. PM_POST_RESTORE only fires when restore fails and the booting kernel must clean up. Code that relies on PM_POST_RESTORE for normal-path cleanup is broken.

Confusing PM notifiers with dev_pm_ops or CPU-hotplug notifiers. PM notifiers are system-wide and fire once, before the freezer; dev_pm_ops callbacks are per-device, after the freezer, in dependency order; and CPU-hotplug uses a completely separate notifier infrastructure. Putting per-device suspend logic in a PM notifier is an anti-pattern — it bypasses the careful device-link ordering the device PM core provides.

Returning a bare negative errno instead of an encoded NOTIFY_* value. A notifier must return NOTIFY_OK/NOTIFY_DONE on success or notifier_from_errno(err) / NOTIFY_BAD to veto. Returning a raw -EBUSY (which happens to be a large negative integer) does not set NOTIFY_STOP_MASK correctly and can silently fail to abort. Use the helpers.

Alternatives and When to Choose Them

Use a PM notifier when work must happen at the system-transition boundary while the system is fully functional — before the freezer for *_PREPARE, after the thaw for POST_*. Typical fits: preloading firmware/memory, stopping/restarting a workqueue or kthread that must not run across the sleep, tuning a subsystem (like RCU) for the transition, or vetoing a transition the subsystem cannot survive.

Use dev_pm_ops callbacks (The Device PM Core and dev_pm_ops) instead when the work is per-device power-state management that must respect device-dependency ordering — gating a device’s clocks, saving its registers, arming it as a wakeup source. The device PM core orders these across the whole device tree; a notifier cannot.

Use runtime PM (Runtime Power Management) when the goal is to power one device down while the system keeps running — that path never touches the PM notifier chain at all.

Production Notes

PM notifiers are used by core subsystems (RCU, the scheduler’s frequency-invariance setup, cpufreq/cpuidle suspend handling), by virtualization (Xen and KVM guests register notifiers to coordinate with the host), and by drivers with the firmware-loading or large-allocation needs described above. Because the chain is global and serial, the kernel community is conservative about adding notifiers — the preferred place for device work remains dev_pm_ops.

For debugging a suspend that aborts in the prepare phase, enable /sys/power/pm_debug_messages and watch dmesg: a vetoing notifier surfaces as the prepare step failing with the errno the notifier returned, before the freezer ever runs. The ftrace suspend_resume tracepoint emits a "freeze_processes" marker; if you see the prepare phase fail before that marker, a notifier is the culprit, not the freezer or a device. The LWN write-up that introduced the mechanism (LWN 235936) lays out the original motivation: driver ->suspend()/->resume() callbacks run at a point where memory is restricted and (on resume) user space is frozen, which is too late for some preparatory work — hence a separate, earlier hook.

See Also