From d503f603b8764a72f7f978e1a39b3d480d7550f0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E9=BB=84=E6=B6=9B?= Date: Mon, 19 May 2014 08:52:22 +0800 Subject: [PATCH] ARM: rockchip: last log v3.0 --- arch/arm/common/fiq_debugger.c | 129 ++---------------------------- arch/arm/mach-rockchip/last_log.c | 75 ++++++++++++----- kernel/printk.c | 25 +++--- 3 files changed, 72 insertions(+), 157 deletions(-) diff --git a/arch/arm/common/fiq_debugger.c b/arch/arm/common/fiq_debugger.c index 17b3b8b45476..a21075ac35fa 100755 --- a/arch/arm/common/fiq_debugger.c +++ b/arch/arm/common/fiq_debugger.c @@ -252,133 +252,24 @@ static void dump_kernel_log(struct fiq_debugger_state *state) #ifdef CONFIG_RK_LAST_LOG #include -extern char *last_log_get(unsigned *size); - -enum log_flags { - LOG_NOCONS = 1, /* already flushed, do not print to console */ - LOG_NEWLINE = 2, /* text ended with a newline */ - LOG_PREFIX = 4, /* text started with a prefix */ - LOG_CONT = 8, /* text is a fragment of a continuation line */ -}; - -struct log { - u64 ts_nsec; /* timestamp in nanoseconds */ - u16 len; /* length of entire record */ - u16 text_len; /* length of text buffer */ - u16 dict_len; /* length of dictionary buffer */ - u8 facility; /* syslog facility */ - u8 flags:5; /* internal record flags */ - u8 level:3; /* syslog level */ -}; - -static void dump_last_kernel_log_raw(struct fiq_debugger_state *state) +extern char *rk_last_log_get(unsigned *size); +static void dump_last_kernel_log(struct fiq_debugger_state *state) { - unsigned size, i, c, w = 0; - char *s = last_log_get(&size); + unsigned size, i, c; + char *s = rk_last_log_get(&size); + for (i = 0; i < size; i++) { if (i % 1024 == 0) wdt_keepalive(); c = s[i]; - if (w % 80 == 79) { - debug_putc(state, '\r'); - debug_putc(state, '\n'); - w = 0; - } if (c == '\n') { - debug_putc(state, '\r'); - debug_putc(state, c); - w = 0; + state->pdata->uart_putc(state->pdev, '\r'); + state->pdata->uart_putc(state->pdev, c); } else if (isascii(c) && isprint(c)) { - debug_putc(state, c); - w++; + state->pdata->uart_putc(state->pdev, c); } } } - -static void dump_last_kernel_log(struct fiq_debugger_state *state) -{ - unsigned size, i, c; - char *s = last_log_get(&size); - unsigned int prev = 0; - - for (;;) { - size_t sz; - struct log *l; - bool prefix = true; - bool newline = true; - const char *text; - unsigned int text_size; - - sz = sizeof(struct log); - if (size < sz) - break; - l = (struct log *)s; - size -= sz; - s += sz; - - if (l->len == 0) - break; - - sz = l->len - sz; - text = s; - text_size = l->text_len; - if (size < sz) - break; - size -= sz; - s += sz; - - if ((prev & LOG_CONT) && !(l->flags & LOG_PREFIX)) - prefix = false; - - if (l->flags & LOG_CONT) { - if ((prev & LOG_CONT) && !(prev & LOG_NEWLINE)) - prefix = false; - - if (!(l->flags & LOG_NEWLINE)) - newline = false; - } - - do { - char *next = memchr(text, '\n', text_size); - size_t text_len; - - if (next) { - text_len = next - text; - next++; - text_size -= next - text; - } else { - text_len = text_size; - } - - if (prefix) { - char buf[32]; - size_t len = 0; - unsigned long rem_nsec = do_div(l->ts_nsec, 1000000000); - unsigned int prefix = (l->facility << 3) | l->level; - - len += snprintf(buf, sizeof(buf), "<%u>", prefix); - len += snprintf(buf + len, sizeof(buf) - len, "[%5lu.%06lu] ", (unsigned long)l->ts_nsec, rem_nsec / 1000); - debug_puts(state, buf); - } - for (i = 0; i < text_len; i++) { - c = text[i]; - if (c == '\n') { - debug_putc(state, '\r'); - debug_putc(state, c); - } else if (isascii(c) && isprint(c)) { - debug_putc(state, c); - } - } - if (next || newline) { - debug_putc(state, '\r'); - debug_putc(state, '\n'); - } - prefix = true; - text = next; - } while (text); - wdt_keepalive(); - } -} #endif static char *mode_name(unsigned cpsr) @@ -850,7 +741,6 @@ static char cmd_buf[][16] = { {"kmsg"}, #ifdef CONFIG_RK_LAST_LOG {"last_kmsg"}, - {"last_kmsg_raw"}, #endif {"version"}, {"sleep"}, @@ -880,7 +770,6 @@ static void debug_help(struct fiq_debugger_state *state) " version Kernel version\n"); #ifdef CONFIG_RK_LAST_LOG debug_printf(state, " last_kmsg Last kernel log\n"); - debug_printf(state, " last_kmsg_raw Last kernel log raw\n"); #endif debug_printf(state, " sleep Allow sleep while in FIQ\n" " nosleep Disable sleep while in FIQ\n" @@ -961,8 +850,6 @@ static bool debug_fiq_exec(struct fiq_debugger_state *state, } else if (!strcmp(cmd, "kmsg")) { dump_kernel_log(state); #ifdef CONFIG_RK_LAST_LOG - } else if (!strcmp(cmd, "last_kmsg_raw")) { - dump_last_kernel_log_raw(state); } else if (!strcmp(cmd, "last_kmsg")) { dump_last_kernel_log(state); #endif diff --git a/arch/arm/mach-rockchip/last_log.c b/arch/arm/mach-rockchip/last_log.c index 23c387d9675d..e3c1d5fbf845 100644 --- a/arch/arm/mach-rockchip/last_log.c +++ b/arch/arm/mach-rockchip/last_log.c @@ -15,15 +15,19 @@ #include #include #include +#include #include #include -#define LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT) -#define LOG_BUF_PAGE_ORDER (CONFIG_LOG_BUF_SHIFT - PAGE_SHIFT) -static char last_log_buf[LOG_BUF_LEN]; -extern void __init switch_log_buf(char *new_log_buf, unsigned size); +#define LOG_BUF_SHIFT CONFIG_LOG_BUF_SHIFT +#define LOG_BUF_LEN (1 << LOG_BUF_SHIFT) +#define LOG_BUF_PAGE_ORDER (LOG_BUF_SHIFT - PAGE_SHIFT) +static char *last_log_buf; +static char *log_buf; +static size_t log_pos; +static char early_log_buf[8192]; -char *last_log_get(unsigned *size) +char *rk_last_log_get(unsigned *size) { *size = LOG_BUF_LEN; return last_log_buf; @@ -64,41 +68,70 @@ static void * __init last_log_vmap(phys_addr_t start, unsigned int page_count) return vmap(pages, page_count + 1, VM_MAP, pgprot_noncached(PAGE_KERNEL)); } -static int __init last_log_init(void) +static int __init rk_last_log_init(void) { - char *log_buf, *new_log_buf; + size_t early_log_size; + char *buf; struct proc_dir_entry *entry; - log_buf = (char *)__get_free_pages(GFP_KERNEL, LOG_BUF_PAGE_ORDER); - if (!log_buf) { + if (!cpu_is_rockchip()) + return 0; + + buf = (char *)__get_free_pages(GFP_KERNEL, LOG_BUF_PAGE_ORDER); + if (!buf) { pr_err("failed to __get_free_pages(%d)\n", LOG_BUF_PAGE_ORDER); return 0; } - new_log_buf = last_log_vmap(virt_to_phys(log_buf), 1 << LOG_BUF_PAGE_ORDER); - if (!new_log_buf) { - pr_err("failed to map %d pages at 0x%08x\n", 1 << LOG_BUF_PAGE_ORDER, virt_to_phys(log_buf)); + log_buf = last_log_vmap(virt_to_phys(buf), 1 << LOG_BUF_PAGE_ORDER); + if (!log_buf) { + pr_err("failed to map %d pages at 0x%08x\n", 1 << LOG_BUF_PAGE_ORDER, virt_to_phys(buf)); + return 0; + } + + last_log_buf = (char *)vmalloc(LOG_BUF_LEN); + if (!last_log_buf) { + pr_err("failed to vmalloc(%d)\n", LOG_BUF_LEN); return 0; } - pr_info("0x%08x map to 0x%p and copy to 0x%p (version 2.2)\n", virt_to_phys(log_buf), new_log_buf, last_log_buf); + memcpy(last_log_buf, buf, LOG_BUF_LEN); + early_log_size = log_pos > sizeof(early_log_buf) ? sizeof(early_log_buf) : log_pos; + memcpy(log_buf, early_log_buf, early_log_size); + memset(log_buf + early_log_size, 0, LOG_BUF_LEN - early_log_size); - memcpy(last_log_buf, new_log_buf, LOG_BUF_LEN); - memset(new_log_buf, 0, LOG_BUF_LEN); - switch_log_buf(new_log_buf, LOG_BUF_LEN); + pr_info("0x%08x map to 0x%p and copy to 0x%p, size 0x%x early 0x%x (version 3.0)\n", virt_to_phys(buf), log_buf, last_log_buf, LOG_BUF_LEN, early_log_size); - entry = proc_create("last_log", S_IRUSR, NULL, &last_log_fops); + entry = proc_create("last_kmsg", S_IRUSR, NULL, &last_log_fops); if (!entry) { pr_err("failed to create proc entry\n"); return 0; } proc_set_size(entry, LOG_BUF_LEN); -#ifndef CONFIG_ANDROID_RAM_CONSOLE - proc_symlink("last_kmsg", NULL, "last_log"); -#endif + proc_symlink("last_log", NULL, "last_kmsg"); return 0; } -postcore_initcall(last_log_init); +early_initcall(rk_last_log_init); + +void rk_last_log_text(char *text, size_t size) +{ + char *buf = log_buf ? log_buf : early_log_buf; + size_t log_size = log_buf ? LOG_BUF_LEN : sizeof(early_log_buf); + size_t pos; + + /* Check overflow */ + pos = log_pos & (log_size - 1); + if (likely(size + pos <= log_size)) + memcpy(&buf[pos], text, size); + else { + size_t first = log_size - pos; + size_t second = size - first; + memcpy(&buf[pos], text, first); + memcpy(&buf[0], text + first, second); + } + + log_pos += size; +} diff --git a/kernel/printk.c b/kernel/printk.c index 4a81eb6e44d6..0f7eb6c133e0 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -306,6 +306,12 @@ static u32 log_next(u32 idx) return idx + msg->len; } +#ifdef CONFIG_RK_LAST_LOG +extern void rk_last_log_text(char *text, size_t size); +static char rk_text[1024]; +static size_t msg_print_text(const struct log *msg, enum log_flags prev, + bool syslog, char *buf, size_t size); +#endif /* insert record into the buffer, discard old ones, update heads */ static void log_store(int facility, int level, enum log_flags flags, u64 ts_nsec, @@ -362,6 +368,10 @@ static void log_store(int facility, int level, memset(log_dict(msg) + dict_len, 0, pad_len); msg->len = sizeof(struct log) + text_len + dict_len + pad_len; +#ifdef CONFIG_RK_LAST_LOG + size = msg_print_text(msg, msg->flags, true, rk_text, sizeof(rk_text)); + rk_last_log_text(rk_text, size); +#endif /* insert message */ log_next_idx += msg->len; log_next_seq++; @@ -1707,21 +1717,6 @@ asmlinkage int printk(const char *fmt, ...) } EXPORT_SYMBOL(printk); -#ifdef CONFIG_RK_LAST_LOG -void __init switch_log_buf(char *new_log_buf, unsigned size) -{ - unsigned long flags; - - if (!new_log_buf || log_buf_len > size) - return; - - raw_spin_lock_irqsave(&logbuf_lock, flags); - memcpy(new_log_buf, log_buf, min(log_buf_len, size)); - log_buf = new_log_buf; - log_buf_len = size; - raw_spin_unlock_irqrestore(&logbuf_lock, flags); -} -#endif /* CONFIG_RK_LAST_LOG */ #if CONFIG_RK_DEBUG_UART >= 0 void console_disable_suspend(void) { -- 2.34.1