7 (KERN_DEBUG)          debug-level messages
 
        log_buf_len=n[KMG]      Sets the size of the printk ring buffer,
-                       in bytes.  n must be a power of two.  The default
-                       size is set in the kernel config file.
+                       in bytes.  n must be a power of two and greater
+                       than the minimal size. The minimal size is defined
+                       by LOG_BUF_SHIFT kernel config parameter. There is
+                       also CONFIG_LOG_CPU_MAX_BUF_SHIFT config parameter
+                       that allows to increase the default size depending on
+                       the number of CPUs. See init/Kconfig for more details.
 
        logo.nologo     [FB] Disables display of the built-in Linux logo.
                        This may be used to provide more screen space for
 
        range 12 21
        default 17
        help
-         Select kernel log buffer size as a power of 2.
+         Select the minimal kernel log buffer size as a power of 2.
+         The final size is affected by LOG_CPU_MAX_BUF_SHIFT config
+         parameter, see below. Any higher size also might be forced
+         by "log_buf_len" boot parameter.
+
          Examples:
-                    17 => 128 KB
+                    17 => 128 KB
                     16 => 64 KB
-                    15 => 32 KB
-                    14 => 16 KB
+                    15 => 32 KB
+                    14 => 16 KB
                     13 =>  8 KB
                     12 =>  4 KB
 
+config LOG_CPU_MAX_BUF_SHIFT
+       int "CPU kernel log buffer size contribution (13 => 8 KB, 17 => 128KB)"
+       range 0 21
+       default 12 if !BASE_SMALL
+       default 0 if BASE_SMALL
+       help
+         This option allows to increase the default ring buffer size
+         according to the number of CPUs. The value defines the contribution
+         of each CPU as a power of 2. The used space is typically only few
+         lines however it might be much more when problems are reported,
+         e.g. backtraces.
+
+         The increased size means that a new buffer has to be allocated and
+         the original static one is unused. It makes sense only on systems
+         with more CPUs. Therefore this value is used only when the sum of
+         contributions is greater than the half of the default kernel ring
+         buffer as defined by LOG_BUF_SHIFT. The default values are set
+         so that more than 64 CPUs are needed to trigger the allocation.
+
+         Also this option is ignored when "log_buf_len" kernel parameter is
+         used as it forces an exact (power of two) size of the ring buffer.
+
+         The number of possible CPUs is used for this computation ignoring
+         hotplugging making the compuation optimal for the the worst case
+         scenerio while allowing a simple algorithm to be used from bootup.
+
+         Examples shift values and their meaning:
+                    17 => 128 KB for each CPU
+                    16 =>  64 KB for each CPU
+                    15 =>  32 KB for each CPU
+                    14 =>  16 KB for each CPU
+                    13 =>   8 KB for each CPU
+                    12 =>   4 KB for each CPU
+
 #
 # Architectures with an unreliable sched_clock() should select this:
 #
 
 #define LOG_ALIGN __alignof__(struct printk_log)
 #endif
 #define __LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
+#define __LOG_CPU_MAX_BUF_LEN (1 << CONFIG_LOG_CPU_MAX_BUF_SHIFT)
 static char __log_buf[__LOG_BUF_LEN] __aligned(LOG_ALIGN);
 static char *log_buf = __log_buf;
 static u32 log_buf_len = __LOG_BUF_LEN;
 }
 early_param("log_buf_len", log_buf_len_setup);
 
+static void __init log_buf_add_cpu(void)
+{
+       unsigned int cpu_extra;
+
+       /*
+        * archs should set up cpu_possible_bits properly with
+        * set_cpu_possible() after setup_arch() but just in
+        * case lets ensure this is valid.
+        */
+       if (num_possible_cpus() == 1)
+               return;
+
+       cpu_extra = (num_possible_cpus() - 1) * __LOG_CPU_MAX_BUF_LEN;
+
+       /* by default this will only continue through for large > 64 CPUs */
+       if (cpu_extra <= __LOG_BUF_LEN / 2)
+               return;
+
+       pr_info("log_buf_len individual max cpu contribution: %d bytes\n",
+               __LOG_CPU_MAX_BUF_LEN);
+       pr_info("log_buf_len total cpu_extra contributions: %d bytes\n",
+               cpu_extra);
+       pr_info("log_buf_len min size: %d bytes\n", __LOG_BUF_LEN);
+
+       log_buf_len_update(cpu_extra + __LOG_BUF_LEN);
+}
+
 void __init setup_log_buf(int early)
 {
        unsigned long flags;
        char *new_log_buf;
        int free;
 
+       if (log_buf != __log_buf)
+               return;
+
+       if (!early && !new_log_buf_len)
+               log_buf_add_cpu();
+
        if (!new_log_buf_len)
                return;