diff mbox series

[U-Boot,9/9] log: Add a way to log error-return values

Message ID 20171228201423.128338-10-sjg@chromium.org
State Accepted
Commit 3707c6ee0d1f939130a62c945b56045d9a83fafc
Delegated to: Simon Glass
Headers show
Series log: Support control over the log output format | expand

Commit Message

Simon Glass Dec. 28, 2017, 8:14 p.m. UTC
When functions return an error it propagates up the stack to the point
where it is reported. Often the error code provides enough information
about the root cause of the error that this is obvious what went wrong.

However in some cases the error may be hard to trace. For example if a
driver uses several devices to perform an operation, it may not be
obvious which one failed.

Add a log_ret() macro to help with this. This can be used to wrap any
error-return value. The logging system will then output a log record when
the original error is generated, making it easy to trace the call stack
of the error.

This macro can significantly impact code size, so its use is controlled
by a Kconfig option, which is enabled for sandbox.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 common/Kconfig            | 13 +++++++++++++
 configs/sandbox_defconfig |  1 +
 doc/README.log            |  8 ++++++++
 include/log.h             | 11 +++++++++++
 4 files changed, 33 insertions(+)

Comments

Simon Glass Jan. 26, 2018, 9:43 p.m. UTC | #1
On 28 December 2017 at 13:14, Simon Glass <sjg@chromium.org> wrote:
> When functions return an error it propagates up the stack to the point
> where it is reported. Often the error code provides enough information
> about the root cause of the error that this is obvious what went wrong.
>
> However in some cases the error may be hard to trace. For example if a
> driver uses several devices to perform an operation, it may not be
> obvious which one failed.
>
> Add a log_ret() macro to help with this. This can be used to wrap any
> error-return value. The logging system will then output a log record when
> the original error is generated, making it easy to trace the call stack
> of the error.
>
> This macro can significantly impact code size, so its use is controlled
> by a Kconfig option, which is enabled for sandbox.
>
> Signed-off-by: Simon Glass <sjg@chromium.org>
> ---
>
>  common/Kconfig            | 13 +++++++++++++
>  configs/sandbox_defconfig |  1 +
>  doc/README.log            |  8 ++++++++
>  include/log.h             | 11 +++++++++++
>  4 files changed, 33 insertions(+)

Applied to u-boot-dm.
diff mbox series

Patch

diff --git a/common/Kconfig b/common/Kconfig
index 4da095a4fd..c9833b3226 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -504,6 +504,19 @@  config LOG_TEST
 	  in various different ways to test that the logging system works
 	  correctly with varoius settings.
 
+config LOG_ERROR_RETURN
+	bool "Log all functions which return an error"
+	depends on LOG
+	help
+	  When an error is returned in U-Boot it is sometimes difficult to
+	  figure out the root cause. For eaxmple, reading from SPI flash may
+	  fail due to a problem in the SPI controller or due to the flash part
+	  not returning the expected information. This option changes
+	  log_ret() to log any errors it sees. With this option disabled,
+	  log_ret() is a nop.
+
+	  You can add log_ret() to all functions which return an error code.
+
 endmenu
 
 config DEFAULT_FDT_FILE
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 7efb4ebf11..41a2e34235 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -18,6 +18,7 @@  CONFIG_PRE_CONSOLE_BUFFER=y
 CONFIG_PRE_CON_BUF_ADDR=0x100000
 CONFIG_LOG=y
 CONFIG_LOG_MAX_LEVEL=6
+CONFIG_LOG_ERROR_RETURN=y
 CONFIG_CMD_CPU=y
 CONFIG_CMD_LICENSE=y
 CONFIG_CMD_BOOTZ=y
diff --git a/doc/README.log b/doc/README.log
index 54d9a8e1b9..2abaee0c10 100644
--- a/doc/README.log
+++ b/doc/README.log
@@ -148,6 +148,14 @@  Also debug() and error() will generate log records  - these use LOG_CATEGORY
 as the category, so you should #define this right at the top of the source
 file to ensure the category is correct.
 
+You can also define CONFIG_LOG_ERROR_RETURN to enable the log_ret() macro. This
+can be used whenever your function returns an error value:
+
+   return log_ret(uclass_first_device(UCLASS_MMC, &dev));
+
+This will write a log record when an error code is detected (a value < 0). This
+can make it easier to trace errors that are generated deep in the call stack.
+
 
 Code size
 ---------
diff --git a/include/log.h b/include/log.h
index 828919a409..68368d5cf1 100644
--- a/include/log.h
+++ b/include/log.h
@@ -159,6 +159,17 @@  void __assert_fail(const char *assertion, const char *file, unsigned int line,
 	({ if (!(x) && _DEBUG) \
 		__assert_fail(#x, __FILE__, __LINE__, __func__); })
 
+#ifdef CONFIG_LOG_ERROR_RETURN
+#define log_ret(_ret) ({ \
+	int __ret = (_ret); \
+	if (__ret < 0) \
+		log(LOG_CATEGORY, LOGL_ERR, "returning err=%d\n", __ret); \
+	__ret; \
+	})
+#else
+#define log_ret(_ret) (_ret)
+#endif
+
 /**
  * struct log_rec - a single log record
  *