From patchwork Mon Mar 7 17:37:22 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kyle Moffett X-Patchwork-Id: 85768 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 27153B70E1 for ; Tue, 8 Mar 2011 04:38:33 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id A1DA7280A7; Mon, 7 Mar 2011 18:38:31 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 9MTIM1JZ7sJv; Mon, 7 Mar 2011 18:38:31 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 850D628088; Mon, 7 Mar 2011 18:38:25 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 6C61628088 for ; Mon, 7 Mar 2011 18:38:22 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id QEkWvJsHpIsX for ; Mon, 7 Mar 2011 18:38:21 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from border.exmeritus.com (wsip-70-167-241-26.dc.dc.cox.net [70.167.241.26]) by theia.denx.de (Postfix) with ESMTP id 1044828089 for ; Mon, 7 Mar 2011 18:38:16 +0100 (CET) Received: from ysera.exmeritus.com (firewall2.exmeritus.com [10.13.38.2]) by border.exmeritus.com (Postfix) with ESMTP id 895CFAC06F; Mon, 7 Mar 2011 12:38:15 -0500 (EST) From: Kyle Moffett To: u-boot@lists.denx.de Date: Mon, 7 Mar 2011 12:37:22 -0500 Message-Id: <1299519462-25320-2-git-send-email-Kyle.D.Moffett@boeing.com> X-Mailer: git-send-email 1.7.2.3 In-Reply-To: <1299519462-25320-1-git-send-email-Kyle.D.Moffett@boeing.com> References: <1299519462-25320-1-git-send-email-Kyle.D.Moffett@boeing.com> Cc: Kyle Moffett , Kyle Moffett Subject: [U-Boot] [PATCH 01/21] Define new system_restart() and emergency_restart() X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.9 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de In preparation for making system restart use a generic set of hooks for boards and architectures, we define some wrappers and weak stubs. The new wrapper functions are: system_restart() - Normal system reboot (IE: user request) emergency_restart() - Critical error response (IE: panic(), etc) During the process of converting all architectures to use the new hooks, the system_restart() and emergency_restart() code will fall back to call the existing do_reset() function. The handler for the "reset" shell command is now do_generic_reset(), which is a trivial wrapper around system_restart(). The new hooks (for architecture and board-support code to define) are: __arch_emergency_restart() __arch_restart() __board_emergency_restart() __board_restart() By default the __(arch|board)_emergency_restart() functions just call the corresponding __(arch|board)_restart() hook. This works for all hardware platforms which have a properly defined hardware reset capability. Signed-off-by: Kyle Moffett Cc: Wolfgang Denk --- api/api.c | 3 +- common/cmd_boot.c | 128 ++++++++++++++++++++++++++++++++++++++++++++- common/cmd_bootm.c | 8 +-- common/hush.c | 2 +- common/main.c | 2 +- examples/api/libgenwrap.c | 5 +- include/_exports.h | 2 +- include/command.h | 13 +++++ lib/vsprintf.c | 2 +- 9 files changed, 152 insertions(+), 13 deletions(-) diff --git a/api/api.c b/api/api.c index 853f010..b65fabd 100644 --- a/api/api.c +++ b/api/api.c @@ -131,7 +131,8 @@ static int API_puts(va_list ap) */ static int API_reset(va_list ap) { - do_reset(NULL, 0, 0, NULL); + if (system_restart()) + return API_ENODEV; /* NOT REACHED */ return 0; diff --git a/common/cmd_boot.c b/common/cmd_boot.c index 7b603d3..c0f26fc 100644 --- a/common/cmd_boot.c +++ b/common/cmd_boot.c @@ -58,6 +58,132 @@ int do_go (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return rcode; } +/* + * emergency_restart() - Restart function to call from panic(), etc. + * + * This may be called from any context when something has gone terribly wrong + * and the system needs a best-effort reboot. + * + * This function will never return. + */ +__attribute__((__noreturn__)) +void emergency_restart(void) +{ + __board_emergency_restart(); + __arch_emergency_restart(); + + /* Fallback to the old do_reset() until everything is converted. */ + do_reset(NULL, 0, 0, NULL); + + printf("EMERGENCY RESTART: All attempts to reboot failed!"); + hang(); +} + +/* + * Architecture/board-specific emergency-restart hooks. + * + * These hooks default to the same as the normal restart hooks. + * + * WARNING: If your platform's "restart" hooks are not a "safe" then you + * must redefine these functions in your port as empty stubs. + * + * Specifically, the following assumptions must be true for these hooks: + * (1) Safe to call from any context (interrupts, etc). + * (2) Must use a hardware mechanism to reset *ALL* system state. + * (3) They must not be interruptible (EG: with Ctrl-C). + */ +__attribute__((__weak__)) +void __board_emergency_restart(void) +{ + __board_restart(); +} + +__attribute__((__weak__)) +void __arch_emergency_restart(void) +{ + __arch_restart(); +} + +/* + * This MUST be called from normal interrupts-on context. If it requires + * extended interaction with external hardware it SHOULD react to Ctrl-C. + * + * If this function fails to guarantee a clean reboot or receives a Ctrl-C + * keystroke it SHOULD return with an error (-1). + */ +int system_restart(void) +{ + int err; + + /* + * Print a nice message and wait a bit to make sure it goes out the + * console properly. + */ + printf ("Restarting...\n"); + udelay(50000); + + /* First let the board code try to reboot */ + err = __board_restart(); + if (err) + goto failed; + + /* Now call into the architecture-specific code */ + err = __arch_restart(); + if (err) + goto failed; + + /* Fallback to the old do_reset() until everything is converted. */ + err = do_reset(NULL, 0, 0, NULL); + +failed: + printf("*** SYSTEM RESTART FAILED ***\n"); + return err; +} + +/* + * Architecture/board-specific restart hooks. + * + * If your implementation of these functions does not meet the requirements + * for the emergency_restart() hooks described above then you MUST separately + * implement those hooks. + */ +__attribute__((__weak__)) +int __board_restart(void) +{ + /* Fallthrough to architecture-specific code */ + return 0; +} + +__attribute__((__weak__)) +int __arch_restart(void) +{ + /* Fallthrough to legacy do_reset() code */ + return 0; +} + +/* + * Generic reset command implementation + * + * This is what you get when you type "reset" at the command line. + */ +int do_generic_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + return system_restart(); +} + +/* + * Empty legacy "do_reset" stub. + * + * This allows a platform using the new __board_restart() and + * __arch_restart() hooks to completely omit the old do_reset() function. + */ +int do_reset_stub(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + return 0; +} +__attribute__((__weak__,__alias__("do_reset_stub"))) +int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); + /* -------------------------------------------------------------------- */ U_BOOT_CMD( @@ -68,7 +194,7 @@ U_BOOT_CMD( ); U_BOOT_CMD( - reset, 1, 0, do_reset, + reset, 1, 0, do_generic_reset, "Perform RESET of the CPU", "" ); diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 18019d6..60e4983 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -645,7 +645,7 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (ret < 0) { if (ret == BOOTM_ERR_RESET) - do_reset (cmdtp, flag, argc, argv); + emergency_restart(); if (ret == BOOTM_ERR_OVERLAP) { if (images.legacy_hdr_valid) { if (image_get_type (&images.legacy_hdr_os_copy) == IH_TYPE_MULTI) @@ -655,7 +655,7 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) puts ("ERROR: new format image overwritten - " "must RESET the board to recover\n"); show_boot_progress (-113); - do_reset (cmdtp, flag, argc, argv); + emergency_restart(); } } if (ret == BOOTM_ERR_UNIMPLEMENTED) { @@ -702,9 +702,7 @@ int do_bootm (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) #ifdef DEBUG puts ("\n## Control returned to monitor - resetting...\n"); #endif - do_reset (cmdtp, flag, argc, argv); - - return 1; + emergency_restart(); } /** diff --git a/common/hush.c b/common/hush.c index 8021a68..f9e57c9 100644 --- a/common/hush.c +++ b/common/hush.c @@ -1036,7 +1036,7 @@ static void get_user_input(struct in_str *i) if (n == -2) { puts("\nTimeout waiting for command\n"); # ifdef CONFIG_RESET_TO_RETRY - do_reset(NULL, 0, 0, NULL); + system_restart(); # else # error "This currently only works with CONFIG_RESET_TO_RETRY enabled" # endif diff --git a/common/main.c b/common/main.c index dcbacc9..abf77a5 100644 --- a/common/main.c +++ b/common/main.c @@ -450,7 +450,7 @@ void main_loop (void) puts ("\nTimed out waiting for command\n"); # ifdef CONFIG_RESET_TO_RETRY /* Reinit board to run initialization code again */ - do_reset (NULL, 0, 0, NULL); + system_restart(); # else return; /* retry autoboot */ # endif diff --git a/examples/api/libgenwrap.c b/examples/api/libgenwrap.c index 873cf34..31bfcf5 100644 --- a/examples/api/libgenwrap.c +++ b/examples/api/libgenwrap.c @@ -81,9 +81,10 @@ void __udelay(unsigned long usec) ub_udelay(usec); } -int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +int system_restart(void) { - ub_reset(); + if (ub_reset()) + return -1; return 0; } diff --git a/include/_exports.h b/include/_exports.h index d89b65b..3d3e511 100644 --- a/include/_exports.h +++ b/include/_exports.h @@ -15,7 +15,7 @@ EXPORT_FUNC(free) EXPORT_FUNC(udelay) EXPORT_FUNC(get_timer) EXPORT_FUNC(vprintf) -EXPORT_FUNC(do_reset) +EXPORT_FUNC(system_restart) EXPORT_FUNC(getenv) EXPORT_FUNC(setenv) EXPORT_FUNC(simple_strtoul) diff --git a/include/command.h b/include/command.h index 8310fe5..ad8c915 100644 --- a/include/command.h +++ b/include/command.h @@ -101,6 +101,19 @@ extern int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); extern int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); extern int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]); +/* Generic system restart functions */ +__attribute__((__noreturn__)) +void emergency_restart(void); +int system_restart(void); + +/* Architecture/board-specific emergency-restart hooks. */ +void __board_emergency_restart(void); +void __arch_emergency_restart(void); + +/* Architecture/board-specific restart hooks. */ +int __board_restart(void); +int __arch_restart(void); + #endif /* __ASSEMBLY__ */ /* diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 61e6f0d..295b60b 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -674,6 +674,6 @@ void panic(const char *fmt, ...) hang(); #else udelay (100000); /* allow messages to go out */ - do_reset (NULL, 0, 0, NULL); + emergency_restart(); #endif }