diff options
Diffstat (limited to 'common/restart.c')
-rw-r--r-- | common/restart.c | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/common/restart.c b/common/restart.c new file mode 100644 index 0000000000..8fd5ffd1a2 --- /dev/null +++ b/common/restart.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2015 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#define pr_fmt(fmt) "restart: " fmt + +#include <common.h> +#include <restart.h> +#include <malloc.h> +#include <of.h> + +static LIST_HEAD(restart_handler_list); + +/** + * restart_handler_register() - register a handler for restarting the system + * @rst: The handler struct + * + * This adds @rst to the list of registered restart handlers. + * + * return: 0 for success or negative error code + */ +int restart_handler_register(struct restart_handler *rst) +{ + if (!rst->name) + rst->name = RESTART_DEFAULT_NAME; + if (!rst->priority) + rst->priority = RESTART_DEFAULT_PRIORITY; + + list_add_tail(&rst->list, &restart_handler_list); + + pr_debug("registering restart handler \"%s\" with priority %d\n", + rst->name, rst->priority); + + return 0; +} + +/** + * restart_handler_register_fn() - register a handler function + * @restart_fn: The restart function + * + * convenience wrapper for restart_handler_register() to register a handler + * with given function and default values otherwise. + * + * return: 0 for success or negative error code + */ +int restart_handler_register_fn(void (*restart_fn)(struct restart_handler *)) +{ + struct restart_handler *rst; + int ret; + + rst = xzalloc(sizeof(*rst)); + + rst->restart = restart_fn; + + ret = restart_handler_register(rst); + + if (ret) + free(rst); + + return ret; +} + +/** + * restart_machine() - reset the whole system + */ +void __noreturn restart_machine(void) +{ + struct restart_handler *rst = NULL, *tmp; + unsigned int priority = 0; + + list_for_each_entry(tmp, &restart_handler_list, list) { + if (tmp->priority > priority) { + priority = tmp->priority; + rst = tmp; + } + } + + if (rst) { + pr_debug("%s: using restart handler %s\n", __func__, rst->name); + console_flush(); + rst->restart(rst); + } + + hang(); +} + +/** + * of_get_restart_priority() - get the desired restart priority from device tree + * @node: The device_node to read the property from + * + * return: The priority + */ +unsigned int of_get_restart_priority(struct device_node *node) +{ + unsigned int priority = RESTART_DEFAULT_PRIORITY; + + of_property_read_u32(node, "restart-priority", &priority); + + return priority; +} |