]> Git Repo - J-linux.git/commitdiff
Merge branch 'rework/nbcon-base' into for-linus
authorPetr Mladek <[email protected]>
Thu, 2 Nov 2023 12:04:59 +0000 (13:04 +0100)
committerPetr Mladek <[email protected]>
Thu, 2 Nov 2023 12:04:59 +0000 (13:04 +0100)
1  2 
kernel/printk/printk.c

diff --combined kernel/printk/printk.c
index 95689eccf0fb274116e3d6d4aa0a0636fccd4ce8,7f40d9122caaebfebde9d5839554bd2d2376df29..be95a6851164793aa707c2c432f7eff363958ebe
@@@ -102,12 -102,6 +102,6 @@@ DEFINE_STATIC_SRCU(console_srcu)
   */
  int __read_mostly suppress_printk;
  
- /*
-  * During panic, heavy printk by other CPUs can delay the
-  * panic and risk deadlock on console resources.
-  */
- static int __read_mostly suppress_panic_printk;
  #ifdef CONFIG_LOCKDEP
  static struct lockdep_map console_lock_dep_map = {
        .name = "console_lock"
@@@ -445,6 -439,12 +439,12 @@@ static int console_msg_format = MSG_FOR
  static DEFINE_MUTEX(syslog_lock);
  
  #ifdef CONFIG_PRINTK
+ /*
+  * During panic, heavy printk by other CPUs can delay the
+  * panic and risk deadlock on console resources.
+  */
+ static int __read_mostly suppress_panic_printk;
  DECLARE_WAIT_QUEUE_HEAD(log_wait);
  /* All 3 protected by @syslog_lock. */
  /* the next printk record to read by syslog(READ) or /proc/kmsg */
@@@ -494,7 -494,7 +494,7 @@@ _DEFINE_PRINTKRB(printk_rb_static, CONF
  
  static struct printk_ringbuffer printk_rb_dynamic;
  
- static struct printk_ringbuffer *prb = &printk_rb_static;
+ struct printk_ringbuffer *prb = &printk_rb_static;
  
  /*
   * We cannot access per-CPU data (e.g. per-CPU flush irq_work) before
@@@ -698,9 -698,6 +698,6 @@@ out
        return len;
  }
  
- static bool printk_get_next_message(struct printk_message *pmsg, u64 seq,
-                                   bool is_extended, bool may_supress);
  /* /dev/kmsg - userspace message inject/listen interface */
  struct devkmsg_user {
        atomic64_t seq;
@@@ -1669,6 -1666,7 +1666,6 @@@ static int syslog_print_all(char __use
  
        prb_rec_init_rd(&r, &info, text, PRINTK_MESSAGE_MAX);
  
 -      len = 0;
        prb_for_each_record(seq, prb, seq, &r) {
                int textlen;
  
@@@ -2348,22 -2346,6 +2345,6 @@@ static bool __pr_flush(struct console *
  
  static u64 syslog_seq;
  
- static size_t record_print_text(const struct printk_record *r,
-                               bool syslog, bool time)
- {
-       return 0;
- }
- static ssize_t info_print_ext_header(char *buf, size_t size,
-                                    struct printk_info *info)
- {
-       return 0;
- }
- static ssize_t msg_print_ext_body(char *buf, size_t size,
-                                 char *text, size_t text_len,
-                                 struct dev_printk_info *dev_info) { return 0; }
- static void console_lock_spinning_enable(void) { }
- static int console_lock_spinning_disable_and_check(int cookie) { return 0; }
- static bool suppress_message_printing(int level) { return false; }
  static bool pr_flush(int timeout_ms, bool reset_on_progress) { return true; }
  static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress) { return true; }
  
@@@ -2717,6 -2699,8 +2698,8 @@@ static void __console_unlock(void
        up_console_sem();
  }
  
+ #ifdef CONFIG_PRINTK
  /*
   * Prepend the message in @pmsg->pbufs->outbuf with a "dropped message". This
   * is achieved by shifting the existing message over and inserting the dropped
   *
   * If @pmsg->pbufs->outbuf is modified, @pmsg->outbuf_len is updated.
   */
- #ifdef CONFIG_PRINTK
- static void console_prepend_dropped(struct printk_message *pmsg, unsigned long dropped)
+ void console_prepend_dropped(struct printk_message *pmsg, unsigned long dropped)
  {
        struct printk_buffers *pbufs = pmsg->pbufs;
        const size_t scratchbuf_sz = sizeof(pbufs->scratchbuf);
        memcpy(outbuf, scratchbuf, len);
        pmsg->outbuf_len += len;
  }
- #else
- #define console_prepend_dropped(pmsg, dropped)
- #endif /* CONFIG_PRINTK */
  
  /*
   * Read and format the specified record (or a later record if the specified
   * of @pmsg are valid. (See the documentation of struct printk_message
   * for information about the @pmsg fields.)
   */
static bool printk_get_next_message(struct printk_message *pmsg, u64 seq,
-                                   bool is_extended, bool may_suppress)
+ bool printk_get_next_message(struct printk_message *pmsg, u64 seq,
+                            bool is_extended, bool may_suppress)
  {
        static int panic_console_dropped;
  
        return true;
  }
  
+ /*
+  * Used as the printk buffers for non-panic, serialized console printing.
+  * This is for legacy (!CON_NBCON) as well as all boot (CON_BOOT) consoles.
+  * Its usage requires the console_lock held.
+  */
+ struct printk_buffers printk_shared_pbufs;
  /*
   * Print one record for the given console. The record printed is whatever
   * record is the next available record for the given console.
   */
  static bool console_emit_next_record(struct console *con, bool *handover, int cookie)
  {
-       static struct printk_buffers pbufs;
        bool is_extended = console_srcu_read_flags(con) & CON_EXTENDED;
-       char *outbuf = &pbufs.outbuf[0];
+       char *outbuf = &printk_shared_pbufs.outbuf[0];
        struct printk_message pmsg = {
-               .pbufs = &pbufs,
+               .pbufs = &printk_shared_pbufs,
        };
        unsigned long flags;
  
@@@ -2918,6 -2903,16 +2902,16 @@@ skip
        return true;
  }
  
+ #else
+ static bool console_emit_next_record(struct console *con, bool *handover, int cookie)
+ {
+       *handover = false;
+       return false;
+ }
+ #endif /* CONFIG_PRINTK */
  /*
   * Print out all remaining records to all consoles.
   *
@@@ -3162,6 -3157,7 +3156,7 @@@ void console_flush_on_panic(enum con_fl
  
        if (mode == CONSOLE_REPLAY_ALL) {
                struct console *c;
+               short flags;
                int cookie;
                u64 seq;
  
  
                cookie = console_srcu_read_lock();
                for_each_console_srcu(c) {
-                       /*
-                        * This is an unsynchronized assignment, but the
-                        * kernel is in "hope and pray" mode anyway.
-                        */
-                       c->seq = seq;
+                       flags = console_srcu_read_flags(c);
+                       if (flags & CON_NBCON) {
+                               nbcon_seq_force(c, seq);
+                       } else {
+                               /*
+                                * This is an unsynchronized assignment. On
+                                * panic legacy consoles are only best effort.
+                                */
+                               c->seq = seq;
+                       }
                }
                console_srcu_read_unlock(cookie);
        }
@@@ -3325,11 -3327,6 +3326,6 @@@ static void try_enable_default_console(
                newcon->flags |= CON_CONSDEV;
  }
  
- #define con_printk(lvl, con, fmt, ...)                        \
-       printk(lvl pr_fmt("%sconsole [%s%d] " fmt),     \
-              (con->flags & CON_BOOT) ? "boot" : "",   \
-              con->name, con->index, ##__VA_ARGS__)
  static void console_init_seq(struct console *newcon, bool bootcon_registered)
  {
        struct console *con;
@@@ -3443,6 -3440,15 +3439,15 @@@ void register_console(struct console *n
                goto unlock;
        }
  
+       if (newcon->flags & CON_NBCON) {
+               /*
+                * Ensure the nbcon console buffers can be allocated
+                * before modifying any global data.
+                */
+               if (!nbcon_alloc(newcon))
+                       goto unlock;
+       }
        /*
         * See if we want to enable this console driver by default.
         *
                err = try_enable_preferred_console(newcon, false);
  
        /* printk() messages are not printed to the Braille console. */
-       if (err || newcon->flags & CON_BRL)
+       if (err || newcon->flags & CON_BRL) {
+               if (newcon->flags & CON_NBCON)
+                       nbcon_free(newcon);
                goto unlock;
+       }
  
        /*
         * If we have a bootconsole, and are switching to a real console,
        newcon->dropped = 0;
        console_init_seq(newcon, bootcon_registered);
  
+       if (newcon->flags & CON_NBCON)
+               nbcon_init(newcon);
        /*
         * Put this console in the list - keep the
         * preferred driver at the head of the list.
@@@ -3578,6 -3590,9 +3589,9 @@@ static int unregister_console_locked(st
         */
        synchronize_srcu(&console_srcu);
  
+       if (console->flags & CON_NBCON)
+               nbcon_free(console);
        console_sysfs_notify();
  
        if (console->exit)
@@@ -3727,11 -3742,11 +3741,12 @@@ late_initcall(printk_late_init)
  /* If @con is specified, only wait for that console. Otherwise wait for all. */
  static bool __pr_flush(struct console *con, int timeout_ms, bool reset_on_progress)
  {
 -      int remaining = timeout_ms;
 +      unsigned long timeout_jiffies = msecs_to_jiffies(timeout_ms);
 +      unsigned long remaining_jiffies = timeout_jiffies;
        struct console *c;
        u64 last_diff = 0;
        u64 printk_seq;
+       short flags;
        int cookie;
        u64 diff;
        u64 seq;
  
        seq = prb_next_seq(prb);
  
 +      /* Flush the consoles so that records up to @seq are printed. */
 +      console_lock();
 +      console_unlock();
 +
        for (;;) {
 +              unsigned long begin_jiffies;
 +              unsigned long slept_jiffies;
 +
                diff = 0;
  
                /*
                 * Hold the console_lock to guarantee safe access to
 -               * console->seq.
 +               * console->seq. Releasing console_lock flushes more
 +               * records in case @seq is still not printed on all
 +               * usable consoles.
                 */
                console_lock();
  
                for_each_console_srcu(c) {
                        if (con && con != c)
                                continue;
+                       flags = console_srcu_read_flags(c);
                        /*
                         * If consoles are not usable, it cannot be expected
                         * that they make forward progress, so only increment
                         */
                        if (!console_is_usable(c))
                                continue;
-                       printk_seq = c->seq;
+                       if (flags & CON_NBCON) {
+                               printk_seq = nbcon_seq_read(c);
+                       } else {
+                               printk_seq = c->seq;
+                       }
                        if (printk_seq < seq)
                                diff += seq - printk_seq;
                }
                console_srcu_read_unlock(cookie);
  
                if (diff != last_diff && reset_on_progress)
 -                      remaining = timeout_ms;
 +                      remaining_jiffies = timeout_jiffies;
  
                console_unlock();
  
                /* Note: @diff is 0 if there are no usable consoles. */
 -              if (diff == 0 || remaining == 0)
 +              if (diff == 0 || remaining_jiffies == 0)
                        break;
  
 -              if (remaining < 0) {
 -                      /* no timeout limit */
 -                      msleep(100);
 -              } else if (remaining < 100) {
 -                      msleep(remaining);
 -                      remaining = 0;
 -              } else {
 -                      msleep(100);
 -                      remaining -= 100;
 -              }
 +              /* msleep(1) might sleep much longer. Check time by jiffies. */
 +              begin_jiffies = jiffies;
 +              msleep(1);
 +              slept_jiffies = jiffies - begin_jiffies;
 +
 +              remaining_jiffies -= min(slept_jiffies, remaining_jiffies);
  
                last_diff = diff;
        }
@@@ -4193,6 -4212,7 +4217,6 @@@ bool kmsg_dump_get_buffer(struct kmsg_d
  
        prb_rec_init_rd(&r, &info, buf, size);
  
 -      len = 0;
        prb_for_each_record(seq, prb, seq, &r) {
                if (r.info->seq >= iter->next_seq)
                        break;
This page took 0.107955 seconds and 4 git commands to generate.