mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 10:41:38 -04:00
printk: allocate kernel log buffer earlier
On larger systems, because of the numerous ACPI, Bootmem and EFI messages, the static log buffer overflows before the larger one specified by the log_buf_len param is allocated. Minimize the overflow by allocating the new log buffer as soon as possible. On kernels without memblock, a later call to setup_log_buf from kernel/init.c is the fallback. [[email protected]: coding-style fixes] [[email protected]: fix CONFIG_PRINTK=n build] Signed-off-by: Mike Travis <[email protected]> Cc: Yinghai Lu <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Cc: Jack Steiner <[email protected]> Cc: Thomas Gleixner <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
This commit is contained in:
parent
95dde50190
commit
162a7e7500
4 changed files with 68 additions and 29 deletions
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/smp.h>
|
||||
#include <linux/security.h>
|
||||
#include <linux/bootmem.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/kexec.h>
|
||||
#include <linux/kdb.h>
|
||||
|
|
@ -167,46 +168,74 @@ void log_buf_kexec_setup(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* requested log_buf_len from kernel cmdline */
|
||||
static unsigned long __initdata new_log_buf_len;
|
||||
|
||||
/* save requested log_buf_len since it's too early to process it */
|
||||
static int __init log_buf_len_setup(char *str)
|
||||
{
|
||||
unsigned size = memparse(str, &str);
|
||||
unsigned long flags;
|
||||
|
||||
if (size)
|
||||
size = roundup_pow_of_two(size);
|
||||
if (size > log_buf_len) {
|
||||
unsigned start, dest_idx, offset;
|
||||
char *new_log_buf;
|
||||
if (size > log_buf_len)
|
||||
new_log_buf_len = size;
|
||||
|
||||
new_log_buf = alloc_bootmem(size);
|
||||
if (!new_log_buf) {
|
||||
printk(KERN_WARNING "log_buf_len: allocation failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&logbuf_lock, flags);
|
||||
log_buf_len = size;
|
||||
log_buf = new_log_buf;
|
||||
|
||||
offset = start = min(con_start, log_start);
|
||||
dest_idx = 0;
|
||||
while (start != log_end) {
|
||||
log_buf[dest_idx] = __log_buf[start & (__LOG_BUF_LEN - 1)];
|
||||
start++;
|
||||
dest_idx++;
|
||||
}
|
||||
log_start -= offset;
|
||||
con_start -= offset;
|
||||
log_end -= offset;
|
||||
spin_unlock_irqrestore(&logbuf_lock, flags);
|
||||
|
||||
printk(KERN_NOTICE "log_buf_len: %d\n", log_buf_len);
|
||||
}
|
||||
out:
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
early_param("log_buf_len", log_buf_len_setup);
|
||||
|
||||
__setup("log_buf_len=", log_buf_len_setup);
|
||||
void __init setup_log_buf(int early)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned start, dest_idx, offset;
|
||||
char *new_log_buf;
|
||||
int free;
|
||||
|
||||
if (!new_log_buf_len)
|
||||
return;
|
||||
|
||||
if (early) {
|
||||
unsigned long mem;
|
||||
|
||||
mem = memblock_alloc(new_log_buf_len, PAGE_SIZE);
|
||||
if (mem == MEMBLOCK_ERROR)
|
||||
return;
|
||||
new_log_buf = __va(mem);
|
||||
} else {
|
||||
new_log_buf = alloc_bootmem_nopanic(new_log_buf_len);
|
||||
}
|
||||
|
||||
if (unlikely(!new_log_buf)) {
|
||||
pr_err("log_buf_len: %ld bytes not available\n",
|
||||
new_log_buf_len);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&logbuf_lock, flags);
|
||||
log_buf_len = new_log_buf_len;
|
||||
log_buf = new_log_buf;
|
||||
new_log_buf_len = 0;
|
||||
free = __LOG_BUF_LEN - log_end;
|
||||
|
||||
offset = start = min(con_start, log_start);
|
||||
dest_idx = 0;
|
||||
while (start != log_end) {
|
||||
unsigned log_idx_mask = start & (__LOG_BUF_LEN - 1);
|
||||
|
||||
log_buf[dest_idx] = __log_buf[log_idx_mask];
|
||||
start++;
|
||||
dest_idx++;
|
||||
}
|
||||
log_start -= offset;
|
||||
con_start -= offset;
|
||||
log_end -= offset;
|
||||
spin_unlock_irqrestore(&logbuf_lock, flags);
|
||||
|
||||
pr_info("log_buf_len: %d\n", log_buf_len);
|
||||
pr_info("early log buf free: %d(%d%%)\n",
|
||||
free, (free * 100) / __LOG_BUF_LEN);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BOOT_PRINTK_DELAY
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue