log: allow for message continuation
authorHeinrich Schuchardt <xypron.glpk@gmx.de>
Sat, 17 Oct 2020 12:31:58 +0000 (14:31 +0200)
committerTom Rini <trini@konsulko.com>
Tue, 27 Oct 2020 17:50:53 +0000 (13:50 -0400)
Some drivers use macro pr_cont() for continuing a message sent via printk.
Hence if we want to convert printk messaging to using the logging system,
we must support continuation of log messages too.

As pr_cont() does not provide a message level we need a means of
remembering the last log level.

With the patch a pseudo log level LOGL_CONT as well as a pseudo log
category LOGC_CONT are introduced. Using these results in the application
of the same log level and category as in the previous log message.

Signed-off-by: Heinrich Schuchardt <xypron.glpk@gmx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
common/log.c
doc/develop/logging.rst
include/asm-generic/global_data.h
include/log.h

index 6a59f2e..d830883 100644 (file)
@@ -191,10 +191,12 @@ static bool log_passes_filters(struct log_device *ldev, struct log_rec *rec)
  * log_dispatch() - Send a log record to all log devices for processing
  *
  * The log record is sent to each log device in turn, skipping those which have
- * filters which block the record
+ * filters which block the record.
  *
- * @rec: Log record to dispatch
- * @return 0 (meaning success)
+ * All log messages created while processing log record @rec are ignored.
+ *
+ * @rec:       log record to dispatch
+ * Return:     0 msg sent, 1 msg not sent while already dispatching another msg
  */
 static int log_dispatch(struct log_rec *rec)
 {
@@ -206,7 +208,7 @@ static int log_dispatch(struct log_rec *rec)
         * as this might result in infinite recursion.
         */
        if (gd->processing_msg)
-               return 0;
+               return 1;
 
        /* Emit message */
        gd->processing_msg = true;
@@ -226,6 +228,12 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file,
        struct log_rec rec;
        va_list args;
 
+       /* Check for message continuation */
+       if (cat == LOGC_CONT)
+               cat = gd->logc_prev;
+       if (level == LOGL_CONT)
+               level = gd->logl_prev;
+
        rec.cat = cat;
        rec.level = level & LOGL_LEVEL_MASK;
        rec.force_debug = level & LOGL_FORCE_DEBUG;
@@ -241,7 +249,10 @@ int _log(enum log_category_t cat, enum log_level_t level, const char *file,
                        gd->log_drop_count++;
                return -ENOSYS;
        }
-       log_dispatch(&rec);
+       if (!log_dispatch(&rec)) {
+               gd->logc_prev = cat;
+               gd->logl_prev = level;
+       }
 
        return 0;
 }
@@ -381,6 +392,8 @@ int log_init(void)
        if (!gd->default_log_level)
                gd->default_log_level = CONFIG_LOG_DEFAULT_LEVEL;
        gd->log_fmt = log_get_default_format();
+       gd->logc_prev = LOGC_NONE;
+       gd->logl_prev = LOGL_INFO;
 
        return 0;
 }
index 28340a4..528280c 100644 (file)
@@ -38,6 +38,9 @@ There are a number logging levels available, in increasing order of verbosity:
 * LOGL_DEBUG_CONTENT - Debug message showing full message content
 * LOGL_DEBUG_IO - Debug message showing hardware I/O access
 
+To continue a log message in a separate call of function log() use
+
+* LOGL_CONT - Use same log level as in previous call
 
 Logging category
 ----------------
@@ -56,6 +59,9 @@ The following main categories are defined:
 * LOGC_DT - Related to device tree control
 * LOGC_EFI - Related to EFI implementation
 
+To continue a log message in a separate call of function log() use
+
+* LOGC_CONT - Use same category as in previous call
 
 Enabling logging
 ----------------
index db83f59..0157af1 100644 (file)
@@ -371,6 +371,18 @@ struct global_data {
         * while another message is being processed.
         */
        bool processing_msg;
+       /**
+        * @logc_prev: logging category of previous message
+        *
+        * This value is used as logging category for continuation messages.
+        */
+       int logc_prev;
+       /**
+        * @logl_pref: logging level of the previous message
+        *
+        * This value is used as logging level for continuation messages.
+        */
+       int logl_prev;
 #endif
 #if CONFIG_IS_ENABLED(BLOBLIST)
        /**
index 6de5e61..58787a3 100644 (file)
@@ -38,6 +38,7 @@ enum log_level_t {
 
        LOGL_FIRST = LOGL_EMERG,
        LOGL_MAX = LOGL_DEBUG_IO,
+       LOGL_CONT = -1,         /* Use same log level as in previous call */
 };
 
 /**
@@ -65,6 +66,7 @@ enum log_category_t {
 
        LOGC_COUNT,     /* Number of log categories */
        LOGC_END,       /* Sentinel value for a list of log categories */
+       LOGC_CONT = -1, /* Use same category as in previous call */
 };
 
 /* Helper to cast a uclass ID to a log category */