601 lines
15 KiB
C
601 lines
15 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (C) 2019 MediaTek Inc.
|
|
*/
|
|
|
|
#include <linux/slab.h>
|
|
#include <linux/proc_fs.h>
|
|
#include <linux/vmalloc.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/file.h>
|
|
#include <linux/string.h>
|
|
#include <linux/seq_file.h>
|
|
#include <linux/of.h>
|
|
#include <linux/of_fdt.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/io.h>
|
|
#include <linux/uaccess.h>
|
|
#include <linux/syscalls.h>
|
|
#include <asm/memory.h>
|
|
#include <linux/of_fdt.h>
|
|
#include <linux/kmsg_dump.h>
|
|
|
|
#include "log_store_kernel.h"
|
|
#include "upmu_common.h"
|
|
|
|
static struct sram_log_header *sram_header;
|
|
static int sram_log_store_status = BUFF_NOT_READY;
|
|
static int dram_log_store_status = BUFF_NOT_READY;
|
|
static char *pbuff;
|
|
static struct pl_lk_log *dram_curlog_header;
|
|
static struct dram_buf_header *sram_dram_buff;
|
|
static bool early_log_disable;
|
|
struct proc_dir_entry *entry;
|
|
static u32 last_boot_phase;
|
|
|
|
|
|
#define EXPDB_PATH "/dev/block/by-name/expdb"
|
|
|
|
#define LOG_BLOCK_SIZE (512)
|
|
#define EXPDB_LOG_SIZE (2*1024*1024)
|
|
|
|
#ifdef CONFIG_MTK_PMIC_COMMON
|
|
u32 set_pmic_boot_phase(u32 boot_phase)
|
|
{
|
|
u32 ret;
|
|
|
|
boot_phase = boot_phase & BOOT_PHASE_MASK;
|
|
ret = pmic_config_interface(0xA0E, boot_phase, BOOT_PHASE_MASK,
|
|
PMIC_BOOT_PHASE_SHIFT);
|
|
return ret;
|
|
}
|
|
|
|
|
|
u32 get_pmic_boot_phase(void)
|
|
{
|
|
u32 value = 0, ret;
|
|
|
|
ret = pmic_read_interface(0xA0E, &value, BOOT_PHASE_MASK,
|
|
PMIC_LAST_BOOT_PHASE_SHIFT);
|
|
if (ret == 0)
|
|
last_boot_phase = value;
|
|
return value;
|
|
}
|
|
#endif
|
|
|
|
/* set the flag whether store log to emmc in next boot phase in pl */
|
|
void store_log_to_emmc_enable(bool value)
|
|
{
|
|
|
|
if (!sram_dram_buff) {
|
|
pr_notice("%s: sram dram buff is NULL.\n", __func__);
|
|
return;
|
|
}
|
|
|
|
if (value) {
|
|
sram_dram_buff->flag |= NEED_SAVE_TO_EMMC;
|
|
} else {
|
|
sram_dram_buff->flag &= ~NEED_SAVE_TO_EMMC;
|
|
sram_header->reboot_count = 0;
|
|
sram_header->save_to_emmc = 0;
|
|
}
|
|
|
|
pr_notice(
|
|
"log_store: sram_dram_buff flag 0x%x, reboot count %d, %d.\n",
|
|
sram_dram_buff->flag, sram_header->reboot_count,
|
|
sram_header->save_to_emmc);
|
|
}
|
|
|
|
void set_boot_phase(u32 step)
|
|
{
|
|
int fd;
|
|
mm_segment_t fs;
|
|
int file_size = 0;
|
|
struct log_emmc_header pEmmc;
|
|
|
|
#ifdef CONFIG_MTK_PMIC_COMMON
|
|
if (sram_header->reserve[SRAM_PMIC_BOOT_PHASE] == FLAG_ENABLE) {
|
|
set_pmic_boot_phase(step);
|
|
if (last_boot_phase == 0)
|
|
get_pmic_boot_phase();
|
|
}
|
|
#endif
|
|
|
|
if ((sram_dram_buff->flag & NEED_SAVE_TO_EMMC) == NEED_SAVE_TO_EMMC) {
|
|
pr_notice("log_store: set boot phase, last boot phase is %d.\n",
|
|
last_boot_phase);
|
|
pr_notice("log_store: not boot up, don't store log to expdb ");
|
|
return;
|
|
}
|
|
|
|
|
|
fs = get_fs();
|
|
set_fs(get_ds());
|
|
|
|
fd = ksys_open(EXPDB_PATH, O_RDWR, 0);
|
|
if (fd < 0) {
|
|
pr_notice("log_store can't open expdb file: %d.\n", fd);
|
|
set_fs(fs);
|
|
return;
|
|
}
|
|
|
|
memset(&pEmmc, 0, sizeof(struct log_emmc_header));
|
|
file_size = ksys_lseek(fd, 0, SEEK_END);
|
|
ksys_lseek(fd, file_size - sram_header->reserve[1], 0);
|
|
ksys_read(fd, (char *)&pEmmc, sizeof(struct log_emmc_header));
|
|
if (pEmmc.sig != LOG_EMMC_SIG) {
|
|
pr_notice("log_store emmc header error, format it.\n");
|
|
memset(&pEmmc, 0, sizeof(struct log_emmc_header));
|
|
pEmmc.sig = LOG_EMMC_SIG;
|
|
} else if (last_boot_phase == 0)
|
|
// get last boot phase
|
|
last_boot_phase = (pEmmc.reserve_flag[BOOT_STEP] >>
|
|
LAST_BOOT_PHASE_SHIFT) & BOOT_PHASE_MASK;
|
|
|
|
// clear now boot phase
|
|
pEmmc.reserve_flag[BOOT_STEP] &= (BOOT_PHASE_MASK <<
|
|
LAST_BOOT_PHASE_SHIFT);
|
|
// set boot phase
|
|
pEmmc.reserve_flag[BOOT_STEP] |= (step << NOW_BOOT_PHASE_SHIFT);
|
|
ksys_lseek(fd, file_size - sram_header->reserve[1], 0);
|
|
ksys_write(fd, (char *)&pEmmc, sizeof(struct log_emmc_header));
|
|
ksys_close(fd);
|
|
set_fs(fs);
|
|
pr_notice("log_store: set boot phase, last boot phase is %d.\n",
|
|
last_boot_phase);
|
|
}
|
|
|
|
u32 get_last_boot_phase(void)
|
|
{
|
|
return last_boot_phase;
|
|
}
|
|
|
|
void log_store_bootup(void)
|
|
{
|
|
/* Boot up finish, don't save log to emmc in next boot.*/
|
|
store_log_to_emmc_enable(false);
|
|
set_boot_phase(BOOT_PHASE_ANDROID);
|
|
}
|
|
|
|
void log_store_to_emmc(void)
|
|
{
|
|
int fd;
|
|
mm_segment_t fs;
|
|
char buff[LOG_BLOCK_SIZE];
|
|
struct log_emmc_header pEmmc;
|
|
struct kmsg_dumper dumper = { .active = true };
|
|
size_t len = 0;
|
|
int file_size, size = 0;
|
|
struct emmc_log kernel_log_config;
|
|
|
|
fs = get_fs();
|
|
set_fs(get_ds());
|
|
|
|
fd = ksys_open(EXPDB_PATH, O_RDWR, 0);
|
|
if (fd < 0) {
|
|
pr_notice("log_store can't open expdb file: %d.\n", fd);
|
|
set_fs(fs);
|
|
return;
|
|
}
|
|
|
|
memset(&pEmmc, 0, sizeof(struct log_emmc_header));
|
|
file_size = ksys_lseek(fd, 0, SEEK_END);
|
|
ksys_lseek(fd, file_size - sram_header->reserve[1], 0);
|
|
ksys_read(fd, (char *)&pEmmc, sizeof(struct log_emmc_header));
|
|
if (pEmmc.sig != LOG_EMMC_SIG) {
|
|
pr_notice("log_store emmc header error, format it.\n");
|
|
memset(&pEmmc, 0, sizeof(struct log_emmc_header));
|
|
pEmmc.sig = LOG_EMMC_SIG;
|
|
}
|
|
kernel_log_config.start = pEmmc.offset;
|
|
|
|
kmsg_dump_rewind_nolock(&dumper);
|
|
memset(buff, 0, LOG_BLOCK_SIZE);
|
|
while (kmsg_dump_get_line_nolock(&dumper, true, buff,
|
|
LOG_BLOCK_SIZE, &len)) {
|
|
if (pEmmc.offset + len + LOG_BLOCK_SIZE > EXPDB_LOG_SIZE)
|
|
pEmmc.offset = 0;
|
|
ksys_lseek(fd, file_size - EXPDB_LOG_SIZE + pEmmc.offset, 0);
|
|
size = ksys_write(fd, buff, len);
|
|
if (size < 0)
|
|
pr_notice_once("write expdb failed:%d.\n", size);
|
|
else
|
|
pEmmc.offset += size;
|
|
memset(buff, 0, LOG_BLOCK_SIZE);
|
|
}
|
|
|
|
kernel_log_config.end = pEmmc.offset;
|
|
kernel_log_config.type = LOG_LAST_KERNEL;
|
|
size = file_size - sram_header->reserve[1] +
|
|
sizeof(struct log_emmc_header) +
|
|
pEmmc.reserve_flag[LOG_INDEX] * sizeof(struct emmc_log);
|
|
ksys_lseek(fd, size, 0);
|
|
ksys_write(fd, (char *)&kernel_log_config, sizeof(struct emmc_log));
|
|
pEmmc.reserve_flag[LOG_INDEX] += 1;
|
|
pEmmc.reserve_flag[LOG_INDEX] = pEmmc.reserve_flag[LOG_INDEX] %
|
|
HEADER_INDEX_MAX;
|
|
ksys_lseek(fd, file_size - sram_header->reserve[1], 0);
|
|
ksys_write(fd, (char *)&pEmmc, sizeof(struct log_emmc_header));
|
|
ksys_close(fd);
|
|
set_fs(fs);
|
|
pr_notice("log_store write expdb done!\n");
|
|
}
|
|
|
|
int set_emmc_config(int type, int value)
|
|
{
|
|
int fd;
|
|
mm_segment_t fs;
|
|
struct log_emmc_header pEmmc;
|
|
int file_size;
|
|
|
|
if (type >= EMMC_STORE_FLAG_TYPE_NR || type < 0) {
|
|
pr_notice("invalid config type: %d.\n", type);
|
|
return -1;
|
|
}
|
|
|
|
fs = get_fs();
|
|
set_fs(get_ds());
|
|
|
|
fd = ksys_open(EXPDB_PATH, O_RDWR, 0);
|
|
if (fd < 0) {
|
|
pr_notice("log_store can't open expdb file: %d.\n", fd);
|
|
set_fs(fs);
|
|
return -1;
|
|
}
|
|
|
|
memset(&pEmmc, 0, sizeof(struct log_emmc_header));
|
|
file_size = ksys_lseek(fd, 0, SEEK_END);
|
|
ksys_lseek(fd, file_size - sram_header->reserve[1], 0);
|
|
ksys_read(fd, (char *)&pEmmc, sizeof(struct log_emmc_header));
|
|
if (pEmmc.sig != LOG_EMMC_SIG) {
|
|
pr_notice("log_store emmc header error.\n");
|
|
ksys_close(fd);
|
|
set_fs(fs);
|
|
return -1;
|
|
}
|
|
|
|
if (type == UART_LOG || type == PRINTK_RATELIMIT ||
|
|
type == KEDUMP_CTL) {
|
|
if (value)
|
|
pEmmc.reserve_flag[type] = FLAG_ENABLE;
|
|
else
|
|
pEmmc.reserve_flag[type] = FLAG_DISABLE;
|
|
} else {
|
|
pEmmc.reserve_flag[type] = value;
|
|
}
|
|
ksys_lseek(fd, file_size - LOG_BLOCK_SIZE, 0);
|
|
ksys_write(fd, (char *)&pEmmc, sizeof(struct log_emmc_header));
|
|
ksys_close(fd);
|
|
set_fs(fs);
|
|
pr_notice("type:%d, value:%d.\n", type, value);
|
|
return 0;
|
|
}
|
|
|
|
int read_emmc_config(struct log_emmc_header *log_header)
|
|
{
|
|
int fd;
|
|
mm_segment_t fs;
|
|
int file_size;
|
|
|
|
fs = get_fs();
|
|
set_fs(get_ds());
|
|
|
|
fd = ksys_open(EXPDB_PATH, O_RDWR, 0);
|
|
if (fd < 0) {
|
|
pr_notice("log_store can't open expdb file: %d.\n", fd);
|
|
set_fs(fs);
|
|
return -1;
|
|
}
|
|
|
|
file_size = ksys_lseek(fd, 0, SEEK_END);
|
|
ksys_lseek(fd, file_size - sram_header->reserve[1], 0);
|
|
ksys_read(fd, (char *)log_header, sizeof(struct log_emmc_header));
|
|
if (log_header->sig != LOG_EMMC_SIG) {
|
|
pr_notice("log_store emmc header error.\n");
|
|
ksys_close(fd);
|
|
set_fs(fs);
|
|
return -1;
|
|
}
|
|
ksys_close(fd);
|
|
set_fs(fs);
|
|
return 0;
|
|
}
|
|
|
|
static void *remap_lowmem(phys_addr_t start, phys_addr_t size)
|
|
{
|
|
struct page **pages;
|
|
phys_addr_t page_start;
|
|
unsigned int page_count;
|
|
pgprot_t prot;
|
|
unsigned int i;
|
|
void *vaddr;
|
|
|
|
page_start = start - offset_in_page(start);
|
|
page_count = DIV_ROUND_UP(size + offset_in_page(start), PAGE_SIZE);
|
|
|
|
prot = pgprot_noncached(PAGE_KERNEL);
|
|
|
|
pages = kmalloc_array(page_count, sizeof(struct page *), GFP_KERNEL);
|
|
if (!pages)
|
|
return NULL;
|
|
|
|
for (i = 0; i < page_count; i++) {
|
|
phys_addr_t addr = page_start + i * PAGE_SIZE;
|
|
|
|
pages[i] = pfn_to_page(addr >> PAGE_SHIFT);
|
|
}
|
|
vaddr = vmap(pages, page_count, VM_MAP, prot);
|
|
kfree(pages);
|
|
if (!vaddr) {
|
|
pr_notice("%s: Failed to map %u pages\n", __func__, page_count);
|
|
return NULL;
|
|
}
|
|
|
|
return vaddr + offset_in_page(start);
|
|
}
|
|
|
|
static int pl_lk_log_show(struct seq_file *m, void *v)
|
|
{
|
|
if (dram_curlog_header == NULL || pbuff == NULL) {
|
|
seq_puts(m, "log buff is null.\n");
|
|
return 0;
|
|
}
|
|
|
|
seq_printf(m, "show buff sig 0x%x, size 0x%x,pl size 0x%x, lk size 0x%x, last_boot step 0x%x!\n",
|
|
dram_curlog_header->sig, dram_curlog_header->buff_size,
|
|
dram_curlog_header->sz_pl, dram_curlog_header->sz_lk, last_boot_phase);
|
|
|
|
if (dram_log_store_status == BUFF_READY)
|
|
if (dram_curlog_header->buff_size >= (dram_curlog_header->off_pl
|
|
+ dram_curlog_header->sz_pl
|
|
+ dram_curlog_header->sz_lk))
|
|
seq_write(m, pbuff+dram_curlog_header->off_pl,
|
|
dram_curlog_header->sz_lk
|
|
+ dram_curlog_header->sz_pl);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int pl_lk_file_open(struct inode *inode, struct file *file)
|
|
{
|
|
return single_open(file, pl_lk_log_show, inode->i_private);
|
|
}
|
|
|
|
static ssize_t pl_lk_file_write(struct file *filp,
|
|
const char *ubuf, size_t cnt, loff_t *data)
|
|
{
|
|
char buf[64];
|
|
long val;
|
|
int ret;
|
|
|
|
if (cnt >= sizeof(buf))
|
|
return -EINVAL;
|
|
|
|
if (copy_from_user(&buf, ubuf, cnt))
|
|
return -EFAULT;
|
|
|
|
buf[cnt] = 0;
|
|
|
|
ret = kstrtoul(buf, 10, (unsigned long *)&val);
|
|
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
switch (val) {
|
|
case 0:
|
|
log_store_bootup();
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
return cnt;
|
|
}
|
|
|
|
static const struct file_operations pl_lk_file_ops = {
|
|
.owner = THIS_MODULE,
|
|
.open = pl_lk_file_open,
|
|
.write = pl_lk_file_write,
|
|
.read = seq_read,
|
|
.llseek = seq_lseek,
|
|
.release = single_release,
|
|
};
|
|
|
|
|
|
static int __init log_store_late_init(void)
|
|
{
|
|
set_boot_phase(BOOT_PHASE_KERNEL);
|
|
if (sram_dram_buff == NULL) {
|
|
pr_notice("log_store: sram header DRAM buff is null.\n");
|
|
dram_log_store_status = BUFF_ALLOC_ERROR;
|
|
return -1;
|
|
}
|
|
|
|
if (!sram_dram_buff->buf_addr || !sram_dram_buff->buf_size) {
|
|
pr_notice("log_store: DRAM buff is null.\n");
|
|
dram_log_store_status = BUFF_ALLOC_ERROR;
|
|
return -1;
|
|
}
|
|
pr_notice("log store:sram_dram_buff addr 0x%x, size 0x%x.\n",
|
|
sram_dram_buff->buf_addr, sram_dram_buff->buf_size);
|
|
|
|
pbuff = remap_lowmem(sram_dram_buff->buf_addr,
|
|
sram_dram_buff->buf_size);
|
|
pr_notice("[PHY layout]log_store_mem:0x%08llx-0x%08llx (0x%llx)\n",
|
|
(unsigned long long)sram_dram_buff->buf_addr,
|
|
(unsigned long long)sram_dram_buff->buf_addr
|
|
+ sram_dram_buff->buf_size - 1,
|
|
(unsigned long long)sram_dram_buff->buf_size);
|
|
if (!pbuff) {
|
|
pr_notice("log_store: ioremap_wc failed.\n");
|
|
dram_log_store_status = BUFF_ERROR;
|
|
return -1;
|
|
}
|
|
|
|
/* check buff flag */
|
|
if (dram_curlog_header->sig != LOG_STORE_SIG) {
|
|
pr_notice("log store: log sig: 0x%x.\n",
|
|
dram_curlog_header->sig);
|
|
dram_log_store_status = BUFF_ERROR;
|
|
return 0;
|
|
}
|
|
|
|
dram_log_store_status = BUFF_READY;
|
|
pr_notice("buff %p, sig %x size %x pl %x, sz %x lk %x, sz %x p %x, l %x\n",
|
|
pbuff, dram_curlog_header->sig,
|
|
dram_curlog_header->buff_size,
|
|
dram_curlog_header->off_pl, dram_curlog_header->sz_pl,
|
|
dram_curlog_header->off_lk, dram_curlog_header->sz_lk,
|
|
dram_curlog_header->pl_flag, dram_curlog_header->lk_flag);
|
|
|
|
entry = proc_create("pl_lk", 0664, NULL, &pl_lk_file_ops);
|
|
if (!entry) {
|
|
pr_notice("log_store: failed to create proc entry\n");
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifndef MODULE
|
|
/* need mapping virtual address to phy address */
|
|
static void store_printk_buff(void)
|
|
{
|
|
phys_addr_t log_buf;
|
|
char *buff;
|
|
int size;
|
|
|
|
if (!sram_dram_buff) {
|
|
pr_notice("log_store: sram_dram_buff is null.\n");
|
|
return;
|
|
}
|
|
buff = log_buf_addr_get();
|
|
log_buf = __pa_symbol(buff);
|
|
size = log_buf_len_get();
|
|
/* support 32/64 bits */
|
|
#ifdef CONFIG_PHYS_ADDR_T_64BIT
|
|
if ((log_buf >> 32) == 0)
|
|
sram_dram_buff->klog_addr = (u32)(log_buf & 0xffffffff);
|
|
else
|
|
sram_dram_buff->klog_addr = 0;
|
|
#else
|
|
sram_dram_buff->klog_addr = log_buf;
|
|
#endif
|
|
sram_dram_buff->klog_size = size;
|
|
if (!early_log_disable)
|
|
sram_dram_buff->flag |= BUFF_EARLY_PRINTK;
|
|
pr_notice("log_store printk_buff addr:0x%x,sz:0x%x,buff-flag:0x%x.\n",
|
|
sram_dram_buff->klog_addr,
|
|
sram_dram_buff->klog_size,
|
|
sram_dram_buff->flag);
|
|
}
|
|
#endif
|
|
|
|
void disable_early_log(void)
|
|
{
|
|
pr_notice("log_store: %s.\n", __func__);
|
|
early_log_disable = true;
|
|
if (!sram_dram_buff) {
|
|
pr_notice("log_store: sram_dram_buff is null.\n");
|
|
return;
|
|
}
|
|
|
|
sram_dram_buff->flag &= ~BUFF_EARLY_PRINTK;
|
|
}
|
|
|
|
|
|
struct mem_desc_ls {
|
|
unsigned int addr;
|
|
unsigned int size;
|
|
};
|
|
static int __init dt_get_log_store(unsigned long node, const char *uname,
|
|
int depth, void *data)
|
|
{
|
|
struct mem_desc_ls *sram_ls;
|
|
|
|
if (depth != 1 || (strcmp(uname, "chosen") != 0
|
|
&& strcmp(uname, "chosen@0") != 0))
|
|
return 0;
|
|
sram_ls = (struct mem_desc_ls *) of_get_flat_dt_prop(node,
|
|
"log_store", NULL);
|
|
if (sram_ls) {
|
|
pr_notice("log_store:[DT] log_store: 0x%x@0x%x\n",
|
|
sram_ls->addr, sram_ls->size);
|
|
*(struct mem_desc_ls *) data = *sram_ls;
|
|
}
|
|
return 1;
|
|
}
|
|
/* store log_store information to */
|
|
static int __init log_store_early_init(void)
|
|
{
|
|
|
|
#if IS_ENABLED(CONFIG_MTK_DRAM_LOG_STORE)
|
|
struct mem_desc_ls sram_ls = { 0 };
|
|
|
|
if (of_scan_flat_dt(dt_get_log_store, &sram_ls))
|
|
pr_info("log_store: get ok, sram addr:0x%x, size:0x%x\n",
|
|
sram_ls.addr, sram_ls.size);
|
|
else
|
|
pr_info("log_store: get fail\n");
|
|
|
|
sram_header = ioremap_wc(sram_ls.addr,
|
|
CONFIG_MTK_DRAM_LOG_STORE_SIZE);
|
|
dram_curlog_header = &(sram_header->dram_curlog_header);
|
|
#else
|
|
pr_notice("log_store: not Found CONFIG_MTK_DRAM_LOG_STORE!\n");
|
|
return -1;
|
|
#endif
|
|
pr_notice("log_store: sram header address 0x%p.\n",
|
|
sram_header);
|
|
if (sram_header->sig != SRAM_HEADER_SIG) {
|
|
pr_notice("log_store: sram header sig 0x%x.\n",
|
|
sram_header->sig);
|
|
sram_log_store_status = BUFF_ERROR;
|
|
sram_header = NULL;
|
|
return -1;
|
|
}
|
|
|
|
sram_dram_buff = &(sram_header->dram_buf);
|
|
if (sram_dram_buff->sig != DRAM_HEADER_SIG) {
|
|
pr_notice("log_store: sram header DRAM sig error");
|
|
sram_log_store_status = BUFF_ERROR;
|
|
sram_dram_buff = NULL;
|
|
return -1;
|
|
}
|
|
|
|
#ifndef MODULE
|
|
/* store printk log buff information to DRAM */
|
|
store_printk_buff();
|
|
#endif
|
|
if (sram_header->reserve[1] == 0 ||
|
|
sram_header->reserve[1] > EXPDB_LOG_SIZE)
|
|
sram_header->reserve[1] = LOG_BLOCK_SIZE;
|
|
|
|
pr_notice("sig 0x%x flag 0x%x add 0x%x size 0x%x offsize 0x%x point 0x%x\n",
|
|
sram_dram_buff->sig, sram_dram_buff->flag,
|
|
sram_dram_buff->buf_addr, sram_dram_buff->buf_size,
|
|
sram_dram_buff->buf_offsize, sram_dram_buff->buf_point);
|
|
|
|
#ifdef MODULE
|
|
log_store_late_init();
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef MODULE
|
|
static void __exit log_store_exit(void)
|
|
{
|
|
if (entry)
|
|
proc_remove(entry);
|
|
}
|
|
|
|
module_init(log_store_early_init);
|
|
module_exit(log_store_exit);
|
|
#else
|
|
early_initcall(log_store_early_init);
|
|
late_initcall(log_store_late_init);
|
|
#endif
|