// SPDX-License-Identifier: GPL-2.0-only/* * linux/kernel/reboot.c * * Copyright (C) 2013 Linus Torvalds */ #define pr_fmt(fmt) "reboot: " fmt #include <linux/atomic.h>#include <linux/ctype.h>#include <linux/export.h>#include <linux/kexec.h>#include <linux/kmod.h>#include <linux/kmsg_dump.h>#include <linux/reboot.h>#include <linux/suspend.h>#include <linux/syscalls.h>#include <linux/syscore_ops.h>#include <linux/uaccess.h> /* * this indicates whether you can reboot with ctrl-alt-del: the default is yes */ static int C_A_D = 1;struct pid *cad_pid;EXPORT_SYMBOL(cad_pid); #if defined(CONFIG_ARM)#define DEFAULT_REBOOT_MODE = REBOOT_HARD#else#define DEFAULT_REBOOT_MODE#endifenum reboot_mode reboot_mode DEFAULT_REBOOT_MODE;EXPORT_SYMBOL_GPL(reboot_mode);enum reboot_mode panic_reboot_mode = REBOOT_UNDEFINED; static enum hw_protection_action hw_protection_action = HWPROT_ACT_SHUTDOWN; /* * This variable is used privately to keep track of whether or not * reboot_type is still set to its default value (i.e., reboot= hasn't * been set on the command line). This is needed so that we can * suppress DMI scanning for reboot quirks. Without it, it's * impossible to override a faulty reboot quirk without recompiling. */int reboot_default = 1;int reboot_cpu;enum reboot_type reboot_type = BOOT_ACPI;int reboot_force; struct sys_off_handler { struct notifier_block nb; int (*sys_off_cb)(struct sys_off_data *data); void *cb_data; enum sys_off_mode mode; bool blocking; void *list; struct device *dev;}; /* * This variable is used to indicate if a halt was initiated instead of a * reboot when the reboot call was invoked with LINUX_REBOOT_CMD_POWER_OFF, but * the system cannot be powered off. This allowes kernel_halt() to notify users * of that. */static bool poweroff_fallback_to_halt; /* * Temporary stub that prevents linkage failure while we're in process * of removing all uses of legacy pm_power_off() around the kernel. */void __weak (*pm_power_off)(void); /* * Notifier list for kernel code which wants to be called * at shutdown. This is used to stop any idling DMA operations * and the like. */static BLOCKING_NOTIFIER_HEAD(reboot_notifier_list); /** * emergency_restart - reboot the system * * Without shutting down any hardware or taking any locks * reboot the system. This is called when we know we are in * trouble so this is our best effort to reboot. This is * safe to call in interrupt context. */void emergency_restart(void){ kmsg_dump(KMSG_DUMP_EMERG); system_state = SYSTEM_RESTART; machine_emergency_restart();}EXPORT_SYMBOL_GPL(emergency_restart); void kernel_restart_prepare(char *cmd){ blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd); system_state = SYSTEM_RESTART; usermodehelper_disable(); device_shutdown();} /** * register_reboot_notifier - Register function to be called at reboot time * @nb: Info about notifier function to be called * * Registers a function with the list of functions * to be called at reboot time. * * Currently always returns zero, as blocking_notifier_chain_register() * always returns zero. */int register_reboot_notifier(struct notifier_block *nb){ return blocking_notifier_chain_register(&reboot_notifier_list, nb);}EXPORT_SYMBOL(register_reboot_notifier); /** * unregister_reboot_notifier - Unregister previously registered reboot notifier * @nb: Hook to be unregistered * * Unregisters a previously registered reboot * notifier function. * * Returns zero on success, or %-ENOENT on failure. */int unregister_reboot_notifier(struct notifier_block *nb){ return blocking_notifier_chain_unregister(&reboot_notifier_list, nb);}EXPORT_SYMBOL(unregister_reboot_notifier); static void devm_unregister_reboot_notifier(struct device *dev, void *res){ WARN_ON(unregister_reboot_notifier(*(struct notifier_block **)res));} int devm_register_reboot_notifier(struct device *dev, struct notifier_block *nb){ struct notifier_block **rcnb; int ret; rcnb = devres_alloc(devm_unregister_reboot_notifier, sizeof(*rcnb), GFP_KERNEL); if (!rcnb) return -ENOMEM; ret = register_reboot_notifier(nb); if (!ret) { *rcnb = nb; devres_add(dev, rcnb); } else { devres_free(rcnb); } return ret;}EXPORT_SYMBOL(devm_register_reboot_notifier); /* * Notifier list for kernel code which wants to be called * to restart the system. */static ATOMIC_NOTIFIER_HEAD(restart_handler_list); /** * register_restart_handler - Register function to be called to reset * the system * @nb: Info about handler function to be called * @nb->priority: Handler priority. Handlers should follow the * following guidelines for setting priorities. * 0: Restart handler of last resort, * with limited restart capabilities * 128: Default restart handler; use if no other * restart handler is expected to be available, * and/or if restart functionality is * sufficient to restart the entire system * 255: Highest priority restart handler, will * preempt all other restart handlers * * Registers a function with code to be called to restart the * system. * * Registered functions will be called from machine_restart as last * step of the restart sequence (if the architecture specific * machine_restart function calls do_kernel_restart - see below * for details). * Registered functions are expected to restart the system immediately. * If more than one function is registered, the restart handler priority * selects which function will be called first. * * Restart handlers are expected to be registered from non-architecture * code, typically from drivers. A typical use case would be a system * where restart functionality is provided through a watchdog. Multiple * restart handlers may exist; for example, one restart handler might * restart the entire system, while another only restarts the CPU. * In such cases, the restart handler which only restarts part of the * hardware is expected to register with low priority to ensure that * it only runs if no other means to restart the system is available. * * Currently always returns zero, as atomic_notifier_chain_register() * always returns zero. */int register_restart_handler(struct notifier_block *nb){ return atomic_notifier_chain_register(&restart_handler_list, nb);}EXPORT_SYMBOL(register_restart_handler); /** * unregister_restart_handler - Unregister previously registered * restart handler * @nb: Hook to be unregistered * * Unregisters a previously registered restart handler function. * * Returns zero on success, or %-ENOENT on failure. */int unregister_restart_handler(struct notifier_block *nb){ return atomic_notifier_chain_unregister(&restart_handler_list, nb);}EXPORT_SYMBOL(unregister_restart_handler); /** * do_kernel_restart - Execute kernel restart handler call chain * * @cmd: pointer to buffer containing command to execute for restart * or %NULL * * Calls functions registered with register_restart_handler. * * Expected to be called from machine_restart as last step of the restart * sequence. * * Restarts the system immediately if a restart handler function has been * registered. Otherwise does nothing. */void do_kernel_restart(char *cmd){ atomic_notifier_call_chain(&restart_handler_list, reboot_mode, cmd);} void migrate_to_reboot_cpu(void){ /* The boot cpu is always logical cpu 0 */ int cpu = reboot_cpu; cpu_hotplug_disable(); /* Make certain the cpu I'm about to reboot on is online */ if (!cpu_online(cpu)) cpu = cpumask_first(cpu_online_mask); /* Prevent races with other tasks migrating this task */ current->flags |= PF_NO_SETAFFINITY; /* Make certain I only run on the appropriate processor */ set_cpus_allowed_ptr(current, cpumask_of(cpu));} /* * Notifier list for kernel code which wants to be called * to prepare system for restart. */static BLOCKING_NOTIFIER_HEAD(restart_prep_handler_list); static void do_kernel_restart_prepare(void){ blocking_notifier_call_chain(&restart_prep_handler_list, 0, NULL);} /** * kernel_restart - reboot the system * @cmd: pointer to buffer containing command to execute for restart * or %NULL * * Shutdown everything and perform a clean reboot. * This is not safe to call in interrupt context. */void kernel_restart(char *cmd){ kernel_restart_prepare(cmd); do_kernel_restart_prepare(); migrate_to_reboot_cpu(); syscore_shutdown(); if (!cmd) pr_emerg("Restarting system\n"); else pr_emerg("Restarting system with command '%s'\n", cmd); kmsg_dump(KMSG_DUMP_SHUTDOWN); machine_restart(cmd);}EXPORT_SYMBOL_GPL(kernel_restart); static void kernel_shutdown_prepare(enum system_states state){ blocking_notifier_call_chain(&reboot_notifier_list, (state == SYSTEM_HALT) ? SYS_HALT : SYS_POWER_OFF, NULL); system_state = state; usermodehelper_disable(); device_shutdown();}/** * kernel_halt - halt the system * * Shutdown everything and perform a clean system halt. */void kernel_halt(void){ kernel_shutdown_prepare(SYSTEM_HALT); migrate_to_reboot_cpu(); syscore_shutdown(); if (poweroff_fallback_to_halt) pr_emerg("Power off not available: System halted instead\n"); else pr_emerg("System halted\n"); kmsg_dump(KMSG_DUMP_SHUTDOWN); machine_halt();}EXPORT_SYMBOL_GPL(kernel_halt); /* * Notifier list for kernel code which wants to be called * to prepare system for power off. */static BLOCKING_NOTIFIER_HEAD(power_off_prep_handler_list); /* * Notifier list for kernel code which wants to be called * to power off system. */static ATOMIC_NOTIFIER_HEAD(power_off_handler_list); static int sys_off_notify(struct notifier_block *nb, unsigned long mode, void *cmd){ struct sys_off_handler *handler; struct sys_off_data data = {}; handler = container_of(nb, struct sys_off_handler, nb); data.cb_data = handler->cb_data; data.mode = mode; data.cmd = cmd; data.dev = handler->dev; return handler->sys_off_cb(&data);} static struct sys_off_handler platform_sys_off_handler; static struct sys_off_handler *alloc_sys_off_handler(int priority){ struct sys_off_handler *handler; gfp_t flags; /* * Platforms like m68k can't allocate sys_off handler dynamically * at the early boot time because memory allocator isn't available yet. */ if (priority == SYS_OFF_PRIO_PLATFORM) { handler = &platform_sys_off_handler; if (handler->cb_data) return ERR_PTR(-EBUSY); } else { if (system_state > SYSTEM_RUNNING) flags = GFP_ATOMIC; else flags = GFP_KERNEL; handler = kzalloc_obj(*handler, flags); if (!handler) return ERR_PTR(-ENOMEM); } return handler;} static void free_sys_off_handler(struct sys_off_handler *handler){ if (handler == &platform_sys_off_handler) memset(handler, 0, sizeof(*handler)); else kfree(handler);} /** * register_sys_off_handler - Register sys-off handler * @mode: Sys-off mode * @priority: Handler priority * @callback: Callback function * @cb_data: Callback argument * * Registers system power-off or restart handler that will be invoked * at the step corresponding to the given sys-off mode. Handler's callback * should return NOTIFY_DONE to permit execution of the next handler in * the call chain or NOTIFY_STOP to break the chain (in error case for * example). * * Multiple handlers can be registered at the default priority level. * * Only one handler can be registered at the non-default priority level, * otherwise ERR_PTR(-EBUSY) is returned. * * Returns a new instance of struct sys_off_handler on success, or * an ERR_PTR()-encoded error code otherwise. */struct sys_off_handler *register_sys_off_handler(enum sys_off_mode mode, int priority, int (*callback)(struct sys_off_data *data), void *cb_data){ struct sys_off_handler *handler; int err; handler = alloc_sys_off_handler(priority); if (IS_ERR(handler)) return handler; switch (mode) { case SYS_OFF_MODE_POWER_OFF_PREPARE: handler->list = &power_off_prep_handler_list; handler->blocking = true; break; case SYS_OFF_MODE_POWER_OFF: handler->list = &power_off_handler_list; break; case SYS_OFF_MODE_RESTART_PREPARE: handler->list = &restart_prep_handler_list; handler->blocking = true; break; case SYS_OFF_MODE_RESTART: handler->list = &restart_handler_list; break; default: free_sys_off_handler(handler); return ERR_PTR(-EINVAL); } handler->nb.notifier_call = sys_off_notify; handler->nb.priority = priority; handler->sys_off_cb = callback; handler->cb_data = cb_data; handler->mode = mode; if (handler->blocking) { if (priority == SYS_OFF_PRIO_DEFAULT) err = blocking_notifier_chain_register(handler->list, &handler->nb); else err = blocking_notifier_chain_register_unique_prio(handler->list, &handler->nb); } else { if (priority == SYS_OFF_PRIO_DEFAULT) err = atomic_notifier_chain_register(handler->list, &handler->nb); else err = atomic_notifier_chain_register_unique_prio(handler->list, &handler->nb); } if (err) { free_sys_off_handler(handler); return ERR_PTR(err); } return handler;}EXPORT_SYMBOL_GPL(register_sys_off_handler); /** * unregister_sys_off_handler - Unregister sys-off handler * @handler: Sys-off handler * * Unregisters given sys-off handler. */void unregister_sys_off_handler(struct sys_off_handler *handler){ int err; if (IS_ERR_OR_NULL(handler)) return; if (handler->blocking) err = blocking_notifier_chain_unregister(handler->list, &handler->nb); else err = atomic_notifier_chain_unregister(handler->list, &handler->nb);Lines 1–500 of 1419. Load more
// SPDX-License-Identifier: GPL-2.0-only /* * linux/kernel/reboot.c * * Copyright (C) 2013 Linus Torvalds */ #define pr_fmt(fmt) "reboot: " fmt #include <linux/atomic.h> #include <linux/ctype.h> #include <linux/export.h> #include <linux/kexec.h> #include <linux/kmod.h> #include <linux/kmsg_dump.h> #include <linux/reboot.h> #include <linux/suspend.h> #include <linux/syscalls.h> #include <linux/syscore_ops.h> #include <linux/uaccess.h> /* * this indicates whether you can reboot with ctrl-alt-del: the default is yes */ static int C_A_D = 1; struct pid *cad_pid; EXPORT_SYMBOL(cad_pid); #if defined(CONFIG_ARM) #define DEFAULT_REBOOT_MODE = REBOOT_HARD #else #define DEFAULT_REBOOT_MODE #endif enum reboot_mode reboot_mode DEFAULT_REBOOT_MODE; EXPORT_SYMBOL_GPL(reboot_mode); enum reboot_mode panic_reboot_mode = REBOOT_UNDEFINED; static enum hw_protection_action hw_protection_action = HWPROT_ACT_SHUTDOWN; /* * This variable is used privately to keep track of whether or not * reboot_type is still set to its default value (i.e., reboot= hasn't * been set on the command line). This is needed so that we can * suppress DMI scanning for reboot quirks. Without it, it's * impossible to override a faulty reboot quirk without recompiling. */ int reboot_default = 1; int reboot_cpu; enum reboot_type reboot_type = BOOT_ACPI; int reboot_force; struct sys_off_handler { struct notifier_block nb; int (*sys_off_cb)(struct sys_off_data *data); void *cb_data; enum sys_off_mode mode; bool blocking; void *list; struct device *dev; }; /* * This variable is used to indicate if a halt was initiated instead of a * reboot when the reboot call was invoked with LINUX_REBOOT_CMD_POWER_OFF, but * the system cannot be powered off. This allowes kernel_halt() to notify users * of that. */ static bool poweroff_fallback_to_halt; /* * Temporary stub that prevents linkage failure while we're in process * of removing all uses of legacy pm_power_off() around the kernel. */ void __weak (*pm_power_off)(void); /* * Notifier list for kernel code which wants to be called * at shutdown. This is used to stop any idling DMA operations * and the like. */ static BLOCKING_NOTIFIER_HEAD(reboot_notifier_list); /** * emergency_restart - reboot the system * * Without shutting down any hardware or taking any locks * reboot the system. This is called when we know we are in * trouble so this is our best effort to reboot. This is * safe to call in interrupt context. */ void emergency_restart(void) { kmsg_dump(KMSG_DUMP_EMERG); system_state = SYSTEM_RESTART; machine_emergency_restart(); } EXPORT_SYMBOL_GPL(emergency_restart); void kernel_restart_prepare(char *cmd) { blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd); system_state = SYSTEM_RESTART; usermodehelper_disable(); device_shutdown(); } /** * register_reboot_notifier - Register function to be called at reboot time * @nb: Info about notifier function to be called * * Registers a function with the list of functions * to be called at reboot time. * * Currently always returns zero, as blocking_notifier_chain_register() * always returns zero. */ int register_reboot_notifier(struct notifier_block *nb) { return blocking_notifier_chain_register(&reboot_notifier_list, nb); } EXPORT_SYMBOL(register_reboot_notifier); /** * unregister_reboot_notifier - Unregister previously registered reboot notifier * @nb: Hook to be unregistered * * Unregisters a previously registered reboot * notifier function. * * Returns zero on success, or %-ENOENT on failure. */ int unregister_reboot_notifier(struct notifier_block *nb) { return blocking_notifier_chain_unregister(&reboot_notifier_list, nb); } EXPORT_SYMBOL(unregister_reboot_notifier); static void devm_unregister_reboot_notifier(struct device *dev, void *res) { WARN_ON(unregister_reboot_notifier(*(struct notifier_block **)res)); } int devm_register_reboot_notifier(struct device *dev, struct notifier_block *nb) { struct notifier_block **rcnb; int ret; rcnb = devres_alloc(devm_unregister_reboot_notifier, sizeof(*rcnb), GFP_KERNEL); if (!rcnb) return -ENOMEM; ret = register_reboot_notifier(nb); if (!ret) { *rcnb = nb; devres_add(dev, rcnb); } else { devres_free(rcnb); } return ret; } EXPORT_SYMBOL(devm_register_reboot_notifier); /* * Notifier list for kernel code which wants to be called * to restart the system. */ static ATOMIC_NOTIFIER_HEAD(restart_handler_list); /** * register_restart_handler - Register function to be called to reset * the system * @nb: Info about handler function to be called * @nb->priority: Handler priority. Handlers should follow the * following guidelines for setting priorities. * 0: Restart handler of last resort, * with limited restart capabilities * 128: Default restart handler; use if no other * restart handler is expected to be available, * and/or if restart functionality is * sufficient to restart the entire system * 255: Highest priority restart handler, will * preempt all other restart handlers * * Registers a function with code to be called to restart the * system. * * Registered functions will be called from machine_restart as last * step of the restart sequence (if the architecture specific * machine_restart function calls do_kernel_restart - see below * for details). * Registered functions are expected to restart the system immediately. * If more than one function is registered, the restart handler priority * selects which function will be called first. * * Restart handlers are expected to be registered from non-architecture * code, typically from drivers. A typical use case would be a system * where restart functionality is provided through a watchdog. Multiple * restart handlers may exist; for example, one restart handler might * restart the entire system, while another only restarts the CPU. * In such cases, the restart handler which only restarts part of the * hardware is expected to register with low priority to ensure that * it only runs if no other means to restart the system is available. * * Currently always returns zero, as atomic_notifier_chain_register() * always returns zero. */ int register_restart_handler(struct notifier_block *nb) { return atomic_notifier_chain_register(&restart_handler_list, nb); } EXPORT_SYMBOL(register_restart_handler); /** * unregister_restart_handler - Unregister previously registered * restart handler * @nb: Hook to be unregistered * * Unregisters a previously registered restart handler function. * * Returns zero on success, or %-ENOENT on failure. */ int unregister_restart_handler(struct notifier_block *nb) { return atomic_notifier_chain_unregister(&restart_handler_list, nb); } EXPORT_SYMBOL(unregister_restart_handler); /** * do_kernel_restart - Execute kernel restart handler call chain * * @cmd: pointer to buffer containing command to execute for restart * or %NULL * * Calls functions registered with register_restart_handler. * * Expected to be called from machine_restart as last step of the restart * sequence. * * Restarts the system immediately if a restart handler function has been * registered. Otherwise does nothing. */ void do_kernel_restart(char *cmd) { atomic_notifier_call_chain(&restart_handler_list, reboot_mode, cmd); } void migrate_to_reboot_cpu(void) { /* The boot cpu is always logical cpu 0 */ int cpu = reboot_cpu; cpu_hotplug_disable(); /* Make certain the cpu I'm about to reboot on is online */ if (!cpu_online(cpu)) cpu = cpumask_first(cpu_online_mask); /* Prevent races with other tasks migrating this task */ current->flags |= PF_NO_SETAFFINITY; /* Make certain I only run on the appropriate processor */ set_cpus_allowed_ptr(current, cpumask_of(cpu)); } /* * Notifier list for kernel code which wants to be called * to prepare system for restart. */ static BLOCKING_NOTIFIER_HEAD(restart_prep_handler_list); static void do_kernel_restart_prepare(void) { blocking_notifier_call_chain(&restart_prep_handler_list, 0, NULL); } /** * kernel_restart - reboot the system * @cmd: pointer to buffer containing command to execute for restart * or %NULL * * Shutdown everything and perform a clean reboot. * This is not safe to call in interrupt context. */ void kernel_restart(char *cmd) { kernel_restart_prepare(cmd); do_kernel_restart_prepare(); migrate_to_reboot_cpu(); syscore_shutdown(); if (!cmd) pr_emerg("Restarting system\n"); else pr_emerg("Restarting system with command '%s'\n", cmd); kmsg_dump(KMSG_DUMP_SHUTDOWN); machine_restart(cmd); } EXPORT_SYMBOL_GPL(kernel_restart); static void kernel_shutdown_prepare(enum system_states state) { blocking_notifier_call_chain(&reboot_notifier_list, (state == SYSTEM_HALT) ? SYS_HALT : SYS_POWER_OFF, NULL); system_state = state; usermodehelper_disable(); device_shutdown(); } /** * kernel_halt - halt the system * * Shutdown everything and perform a clean system halt. */ void kernel_halt(void) { kernel_shutdown_prepare(SYSTEM_HALT); migrate_to_reboot_cpu(); syscore_shutdown(); if (poweroff_fallback_to_halt) pr_emerg("Power off not available: System halted instead\n"); else pr_emerg("System halted\n"); kmsg_dump(KMSG_DUMP_SHUTDOWN); machine_halt(); } EXPORT_SYMBOL_GPL(kernel_halt); /* * Notifier list for kernel code which wants to be called * to prepare system for power off. */ static BLOCKING_NOTIFIER_HEAD(power_off_prep_handler_list); /* * Notifier list for kernel code which wants to be called * to power off system. */ static ATOMIC_NOTIFIER_HEAD(power_off_handler_list); static int sys_off_notify(struct notifier_block *nb, unsigned long mode, void *cmd) { struct sys_off_handler *handler; struct sys_off_data data = {}; handler = container_of(nb, struct sys_off_handler, nb); data.cb_data = handler->cb_data; data.mode = mode; data.cmd = cmd; data.dev = handler->dev; return handler->sys_off_cb(&data); } static struct sys_off_handler platform_sys_off_handler; static struct sys_off_handler *alloc_sys_off_handler(int priority) { struct sys_off_handler *handler; gfp_t flags; /* * Platforms like m68k can't allocate sys_off handler dynamically * at the early boot time because memory allocator isn't available yet. */ if (priority == SYS_OFF_PRIO_PLATFORM) { handler = &platform_sys_off_handler; if (handler->cb_data) return ERR_PTR(-EBUSY); } else { if (system_state > SYSTEM_RUNNING) flags = GFP_ATOMIC; else flags = GFP_KERNEL; handler = kzalloc_obj(*handler, flags); if (!handler) return ERR_PTR(-ENOMEM); } return handler; } static void free_sys_off_handler(struct sys_off_handler *handler) { if (handler == &platform_sys_off_handler) memset(handler, 0, sizeof(*handler)); else kfree(handler); } /** * register_sys_off_handler - Register sys-off handler * @mode: Sys-off mode * @priority: Handler priority * @callback: Callback function * @cb_data: Callback argument * * Registers system power-off or restart handler that will be invoked * at the step corresponding to the given sys-off mode. Handler's callback * should return NOTIFY_DONE to permit execution of the next handler in * the call chain or NOTIFY_STOP to break the chain (in error case for * example). * * Multiple handlers can be registered at the default priority level. * * Only one handler can be registered at the non-default priority level, * otherwise ERR_PTR(-EBUSY) is returned. * * Returns a new instance of struct sys_off_handler on success, or * an ERR_PTR()-encoded error code otherwise. */ struct sys_off_handler * register_sys_off_handler(enum sys_off_mode mode, int priority, int (*callback)(struct sys_off_data *data), void *cb_data) { struct sys_off_handler *handler; int err; handler = alloc_sys_off_handler(priority); if (IS_ERR(handler)) return handler; switch (mode) { case SYS_OFF_MODE_POWER_OFF_PREPARE: handler->list = &power_off_prep_handler_list; handler->blocking = true; break; case SYS_OFF_MODE_POWER_OFF: handler->list = &power_off_handler_list; break; case SYS_OFF_MODE_RESTART_PREPARE: handler->list = &restart_prep_handler_list; handler->blocking = true; break; case SYS_OFF_MODE_RESTART: handler->list = &restart_handler_list; break; default: free_sys_off_handler(handler); return ERR_PTR(-EINVAL); } handler->nb.notifier_call = sys_off_notify; handler->nb.priority = priority; handler->sys_off_cb = callback; handler->cb_data = cb_data; handler->mode = mode; if (handler->blocking) { if (priority == SYS_OFF_PRIO_DEFAULT) err = blocking_notifier_chain_register(handler->list, &handler->nb); else err = blocking_notifier_chain_register_unique_prio(handler->list, &handler->nb); } else { if (priority == SYS_OFF_PRIO_DEFAULT) err = atomic_notifier_chain_register(handler->list, &handler->nb); else err = atomic_notifier_chain_register_unique_prio(handler->list, &handler->nb); } if (err) { free_sys_off_handler(handler); return ERR_PTR(err); } return handler; } EXPORT_SYMBOL_GPL(register_sys_off_handler); /** * unregister_sys_off_handler - Unregister sys-off handler * @handler: Sys-off handler * * Unregisters given sys-off handler. */ void unregister_sys_off_handler(struct sys_off_handler *handler) { int err; if (IS_ERR_OR_NULL(handler)) return; if (handler->blocking) err = blocking_notifier_chain_unregister(handler->list, &handler->nb); else err = atomic_notifier_chain_unregister(handler->list, &handler->nb);