You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1790 lines
55 KiB

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2009-2020. All rights reserved.
* Description: log drv
* Author: Hisilicon
* Create: 2009-12-17
*/
#include "drv_log.h"
#include <mntn/rdr_log.h>
#include <linux/rtc.h>
#include <linux/huanglong/securec.h>
#include "td_type.h"
#include "soc_log.h"
#include "osal_ext.h"
#include "drv_dev_ext.h"
#include "drv_module_ext.h"
#include "drv_log_ext.h"
#include "drv_sys_ext.h"
#include "drv_ioctl_log.h"
#include "drv_log.h"
typedef struct {
struct dma_buf *dmabuf;
td_u8 *virt_addr;
} log_ion_buf;
#define LOG_MSG_BUF_RESERVE (4 * 1024)
static log_ion_buf g_log_cfg_buf;
/* kernel-state pointer of log control info */ /* CNcomment: 打印控制信息的内核态指针 */
static log_cfg_info *g_log_cfg_info;
static td_bool g_log_init = TD_FALSE;
#define LOG_MAX_FILE_SIZE 120U /* 120M */
#define LOG_MIN_FILE_SIZE 1U /* 1M */
#define LOG_DEFAULT_FILE_SIZE 12U /* 12M */
#if defined(CONFIG_SOCT_LOG_NETWORK_SUPPORT) || defined(CONFIG_SOCT_LOG_UDISK_SUPPORT)
#define LOG_MAX_FILE_CNT (4) /* Save up to 5 log files */
static log_ion_buf g_log_msg_buf;
static td_u64 g_log_write_len_count = 0;
static td_u32 g_log_file_count = 0;
#endif
static log_buf_info g_log_msg_info;
static osal_semaphore g_log_k_mutex;
osal_semaphore g_log_store_mutex;
DEFINE_SPINLOCK(g_log_lock);
#define log_file_lock() osal_sem_down_interruptible(&g_log_k_mutex)
#define log_file_unlock() osal_sem_up(&g_log_k_mutex)
#define log_store_lock() osal_sem_down_interruptible(&g_log_store_mutex)
#define log_store_unlock() osal_sem_up(&g_log_store_mutex)
#define STORE_LOG_WAKE_UP_SIZE 1000
#define LOG_RTC_TIME_LENGH 19
#define LOG_WAIT_DATA_TIMEOUT 1000 /* 1s */
/* this variable will be used by /kmod/load script */
static td_u32 g_log_buf_size = 10 * 256 * LOG_MSG_BUF_RESERVE; /* Multiply by 256 means buf_size is 1M,10M total */
static td_char g_log_path_buf[LOG_MAX_FILE_NAME_LENTH] = "/tmp";
static td_char *g_udisk_log_file = g_log_path_buf;
static td_bool g_set_log_file_flag = TD_FALSE;
static td_char g_store_path_buf[LOG_MAX_FILE_NAME_LENTH] = "/mnt";
td_char *g_store_path = g_store_path_buf;
static td_u32 g_default_log_size = LOG_DEFAULT_FILE_SIZE * 1024 * 1024; /* Multiply by 1024 means buf_size is 16M */
td_char *g_debug_level_name[SOC_LOG_LEVEL_MAX + 1] = {
"ALERT", "FATAL", "ERROR", "WARN", "NOTICE", "INFO", "DEBUG", "TRACE", "MAX"
};
static td_u32 g_default_log_level = SOC_LOG_LEVEL_ERROR;
static log_store_info_t g_log_store_info = {
.store_log_enable = TD_FALSE,
.store_log_thread_exist = TD_FALSE,
.store_log_poll_new = TD_FALSE,
.store_log_len = 0,
};
td_void drv_log_store_enable(const td_bool *enable)
{
if (enable == TD_NULL) {
return;
}
if (g_set_log_file_flag == TD_TRUE) {
g_log_store_info.store_log_enable = TD_FALSE;
} else {
g_log_store_info.store_log_enable = *enable;
}
g_log_store_info.store_log_thread_exist = *enable;
return;
}
td_void drv_log_get_store_status(td_bool *store_enable, td_bool *store_thread_exist)
{
if (store_enable == TD_NULL || store_thread_exist == TD_NULL) {
return;
}
*store_enable = g_log_store_info.store_log_enable;
*store_thread_exist = g_log_store_info.store_log_thread_exist;
return;
}
unsigned int drv_log_store_poll(osal_poll *osal_poll)
{
unsigned int poll_mask = 0;
if (g_log_store_info.store_log_thread_exist == TD_TRUE) {
if (g_log_store_info.store_log_poll_new == TD_TRUE) {
poll_mask |= OSAL_POLLIN;
g_log_store_info.store_log_poll_new = TD_FALSE;
} else {
osal_poll_wait(osal_poll, &g_log_store_info.poll_wait_queue);
}
}
return poll_mask;
}
static td_void drv_log_reset_buf(td_void)
{
td_ulong flags;
spin_lock_irqsave(&g_log_lock, flags);
g_log_msg_info.read = g_log_msg_info.write;
g_log_msg_info.reset_cnt++;
spin_unlock_irqrestore(&g_log_lock, flags);
}
static td_s32 drv_log_wait_condition(const td_void *param)
{
return (((log_buf_info *)param)->write != ((log_buf_info *)param)->read);
}
static td_s32 log_data_buf_copy(td_u8 *buf, td_u32 buf_size, const td_u8 *src, td_u32 copy_len,
td_bool b_kernel_copy)
{
errno_t err_ret;
if (b_kernel_copy == TD_FALSE) {
if (osal_copy_to_user(buf, src, copy_len)) {
soc_log_err("copy_to_user error\n");
return TD_FAILURE;
}
} else {
err_ret = memcpy_s(buf, buf_size, src, copy_len);
if (err_ret != EOK) {
soc_log_err("secure func call error\n");
return TD_FAILURE;
}
}
return TD_SUCCESS;
}
static td_s32 log_read_data(td_u8 *buf, td_u32 buf_len, log_buf_info *msg_info_now,
td_u32 *copy_len, td_bool b_kernel_copy)
{
td_u32 buf_used, data_part_one, data_part_two, data_len, new_read_addr;
td_s32 ret;
/* not support log when uart close or user version */
#if defined (CONFIG_CLOSE_UART0) || defined (ANDROID_BUILD_USER)
return TD_SUCCESS;
#endif
if (osal_get_buildvariant() == OSAL_BUILDVARIANT_USER) {
return TD_SUCCESS;
}
if (msg_info_now->write < msg_info_now->read) {
buf_used = msg_info_now->buf_size - msg_info_now->read + msg_info_now->write;
data_part_one = msg_info_now->buf_size - msg_info_now->read;
data_part_two = msg_info_now->write;
} else {
buf_used = msg_info_now->write - msg_info_now->read;
data_part_one = buf_used;
data_part_two = 0;
}
*copy_len = (buf_len <= (data_part_one + data_part_two)) ? (buf_len) : (data_part_one + data_part_two);
data_len = (data_part_one >= *copy_len) ? (*copy_len) : (data_part_one);
ret = log_data_buf_copy(buf, buf_len, msg_info_now->start_virt_addr + msg_info_now->read, data_len, b_kernel_copy);
if (ret != TD_SUCCESS) {
return TD_FAILURE;
}
if (data_part_one < *copy_len) {
ret = log_data_buf_copy(buf + data_part_one, buf_len - data_part_one,
msg_info_now->start_virt_addr, *copy_len - data_part_one, b_kernel_copy);
if (ret != TD_SUCCESS) {
soc_log_err("log data copy error\n");
return TD_FAILURE;
}
}
new_read_addr = (data_part_one >= *copy_len) ? (msg_info_now->read + *copy_len) : (*copy_len - data_part_one);
new_read_addr = (new_read_addr >= msg_info_now->buf_size) ? (0) : (new_read_addr);
return new_read_addr;
}
static td_s32 log_buffer_read(td_u8 *buf, td_u32 buf_len, td_u32 *p_copy_len, td_bool b_kernel_copy)
{
log_buf_info msg_info_now;
unsigned long flags;
td_s32 ret;
errno_t err_ret;
spin_lock_irqsave(&g_log_lock, flags);
err_ret = memcpy_s(&msg_info_now, sizeof(log_buf_info), &g_log_msg_info, sizeof(g_log_msg_info));
spin_unlock_irqrestore(&g_log_lock, flags);
if (err_ret != EOK) {
soc_log_err("secure func call error\n");
return TD_FAILURE;
}
ret = log_read_data(buf, buf_len, &msg_info_now, p_copy_len, b_kernel_copy);
if (ret < 0) {
soc_log_err("call log_read_data error\n");
return TD_FAILURE;
}
spin_lock_irqsave(&g_log_lock, flags);
g_log_store_info.store_log_len -= *p_copy_len;
if (msg_info_now.reset_cnt == g_log_msg_info.reset_cnt) {
g_log_msg_info.read = (td_u32)ret;
}
spin_unlock_irqrestore(&g_log_lock, flags);
return TD_SUCCESS;
}
td_s32 ext_drv_log_read_buf(td_u8 *buf, td_u32 buf_len, td_u32 *copy_len, td_bool *status,
td_bool is_kernel_copy)
{
td_s32 ret;
if (g_log_msg_info.buf_size == 0) {
soc_log_err("Log Buffer size is 0, Please confige the Buffer size, for example:");
soc_log_err(" Config buffer size 500K: insmod soc_cmpi.ko g_log_buf_size = 0x80000");
return TD_FAILURE;
}
if (buf == TD_NULL) {
soc_log_err("buf is null\n");
return TD_FAILURE;
}
if (status == TD_NULL) {
soc_log_err("status is null\n");
return TD_FAILURE;
}
*status = g_log_store_info.store_log_enable;
if (g_log_msg_info.write == g_log_msg_info.read) {
if (g_set_log_file_flag == TD_TRUE || g_log_store_info.store_log_enable == TD_TRUE) {
return TD_FAILURE;
} else {
/* the following code segment will pending when reboot or reload ko */
ret = osal_wait_timeout_interruptible(&g_log_msg_info.wq_no_data, drv_log_wait_condition,
&g_log_msg_info, LOG_WAIT_DATA_TIMEOUT);
if (ret == 0 && (g_log_msg_info.write == g_log_msg_info.read)) {
return TD_FAILURE;
}
}
}
ret = log_buffer_read(buf, buf_len, copy_len, is_kernel_copy);
if (ret != TD_SUCCESS) {
soc_log_err("call log_buffer_read failed !\n");
return TD_FAILURE;
}
return TD_SUCCESS;
}
static td_s32 drv_log_write(const td_u8 *buf, td_u32 copy_len1,
td_u32 copy_len2, td_u32 msg_from_pos, td_u32 new_write_addr)
{
td_s32 ret;
if (copy_len1 > 0) {
if (msg_from_pos == LOG_MSG_FROM_KERNEL) {
ret = memcpy_s((g_log_msg_info.write + g_log_msg_info.start_virt_addr),
g_log_msg_info.buf_size - g_log_msg_info.write, buf, copy_len1);
if (ret != EOK) {
soc_log_err("memcpy_s error !\n");
return TD_FAILURE;
}
} else {
if (osal_copy_from_user((g_log_msg_info.write + g_log_msg_info.start_virt_addr), buf, copy_len1)) {
soc_log_err("copy_from_user error\n");
return TD_FAILURE;
}
}
}
if (copy_len2 > 0) {
if (msg_from_pos == LOG_MSG_FROM_KERNEL) {
ret = memcpy_s(g_log_msg_info.start_virt_addr, g_log_msg_info.buf_size, (buf + copy_len1), copy_len2);
if (ret != EOK) {
soc_log_err("memcpy_s error !\n");
return TD_FAILURE;
}
} else {
if (osal_copy_from_user(g_log_msg_info.start_virt_addr, (buf + copy_len1), copy_len2)) {
soc_log_err("copy_from_user error\n");
return TD_FAILURE;
}
}
}
g_log_msg_info.write = new_write_addr;
if (g_set_log_file_flag != TD_TRUE || g_log_store_info.store_log_enable != TD_TRUE) {
osal_wait_wakeup(&g_log_msg_info.wq_no_data);
}
return TD_SUCCESS;
}
td_s32 ext_drv_log_write_buf(const td_u8 *buf, td_u32 msg_len, td_u32 msg_from_pos)
{
td_u32 copy_len1, copy_len2, new_write_addr, cond;
td_ulong flags;
td_s32 ret;
/* not support log when uart close or user version */
#if defined (CONFIG_CLOSE_UART0) || defined (ANDROID_BUILD_USER)
return TD_SUCCESS;
#endif
if (osal_get_buildvariant() == OSAL_BUILDVARIANT_USER) {
return TD_SUCCESS;
}
cond = ((g_log_msg_info.buf_size == 0) || (buf == TD_NULL || msg_len >= g_log_buf_size));
if (cond) {
soc_log_err("param invalid!\n");
return TD_FAILURE;
}
spin_lock_irqsave(&g_log_lock, flags);
g_log_store_info.store_log_len += msg_len;
spin_unlock_irqrestore(&g_log_lock, flags);
if (g_log_store_info.store_log_len > STORE_LOG_WAKE_UP_SIZE) {
g_log_store_info.store_log_poll_new = TD_TRUE;
osal_wait_wakeup(&g_log_store_info.poll_wait_queue);
}
if (g_log_msg_info.write < g_log_msg_info.read) {
if ((g_log_msg_info.read - g_log_msg_info.write) < LOG_MSG_BUF_RESERVE) {
drv_log_reset_buf();
}
} else {
if ((g_log_msg_info.write - g_log_msg_info.read) > (g_log_msg_info.buf_size - LOG_MSG_BUF_RESERVE)) {
drv_log_reset_buf();
}
}
if ((msg_len + g_log_msg_info.write) >= g_log_msg_info.buf_size) {
copy_len1 = g_log_msg_info.buf_size - g_log_msg_info.write;
copy_len2 = msg_len - copy_len1;
new_write_addr = copy_len2;
} else {
copy_len1 = msg_len;
copy_len2 = 0;
new_write_addr = msg_len + g_log_msg_info.write;
}
/*
* protect with semaphore while two module write at the same time
* CNcomment: 两个模块同时写要做信号量保护
*/
spin_lock_irqsave(&g_log_lock, flags);
ret = drv_log_write(buf, copy_len1, copy_len2, msg_from_pos, new_write_addr);
if (ret != TD_SUCCESS) {
spin_unlock_irqrestore(&g_log_lock, flags);
return TD_FAILURE;
}
spin_unlock_irqrestore(&g_log_lock, flags);
return TD_SUCCESS;
}
td_void log_get_rtc_time(td_char *rtc_time, td_u32 len)
{
osal_rtc_time tm = {0};
osal_timeval tv;
td_u32 cur_usec;
td_s32 ret;
if (rtc_time == TD_NULL) {
soc_log_err("rtc_time is null\n");
return;
}
/* 获取当前的UTC时间 */
osal_gettimeofday(&tv);
/* 把UTC时间调整为本地时间 */
tv.tv_sec -= sys_tz.tz_minuteswest * 60; /* 60 表示min与s的换算关系 */
/* 算出时间中的年月日等数值到tm中 */
osal_rtc_time_to_tm(tv.tv_sec, &tm);
cur_usec = (td_u32)tv.tv_usec / 1000; /* 1000 表示s/ms/us的换算关系 */
ret = snprintf_s(rtc_time, len, LOG_RTC_TIME_LENGH, "%02d-%02d %02d:%02d:%02d.%03d", tm.tm_mon + 1,
tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, cur_usec);
if (ret < 0) {
soc_print("call snprintf_s failed!\n");
return;
}
rtc_time[LOG_RTC_TIME_LENGH - 1] = ' ';
return;
}
td_s32 drv_log_add_module(const td_char *name, td_u32 mod_id)
{
td_s32 ret;
if (name == TD_NULL || g_log_cfg_info == TD_NULL || mod_id >= LOG_CFG_BUF_SIZE / sizeof(log_cfg_info)) {
return TD_FAILURE;
}
ret = strncpy_s(g_log_cfg_info[mod_id].module_name, sizeof(g_log_cfg_info[mod_id].module_name),
name, strlen(name));
if (ret != EOK) {
soc_log_err("strncpy_s failed\n");
return TD_FAILURE;
}
g_log_cfg_info[mod_id].module_name[sizeof(g_log_cfg_info[mod_id].module_name) - 1] = '\0';
return TD_SUCCESS;
}
#define DEFAULT_LOG_QUOTA (12288)
td_s32 drv_log_remove_module(td_u32 mod_id)
{
td_s32 ret;
if (g_log_cfg_info == TD_NULL || mod_id >= LOG_CFG_BUF_SIZE / sizeof(log_cfg_info)) {
return TD_FAILURE;
}
g_log_cfg_info[mod_id].log_level = (td_u8)g_default_log_level;
g_log_cfg_info[mod_id].log_print_pos = LOG_OUTPUT_SERIAL;
g_log_cfg_info[mod_id].log_quota = DEFAULT_LOG_QUOTA;
ret = snprintf_s(g_log_cfg_info[mod_id].module_name, sizeof(g_log_cfg_info[mod_id].module_name),
strlen("Invalid"), "Invalid");
if (ret < 0) {
soc_log_err("snprintf_s failed\n");
return TD_FAILURE;
}
g_log_cfg_info[mod_id].module_name[sizeof(g_log_cfg_info[mod_id].module_name) - 1] = '\0';
return TD_SUCCESS;
}
td_void drv_log_set_module(td_u32 mod_id)
{
td_s32 ret;
module_detail_info module_data;
if (g_log_cfg_info == TD_NULL || mod_id >= LOG_CFG_BUF_SIZE / sizeof(log_cfg_info)) {
return;
}
ret = ext_drv_module_get_data(mod_id, &module_data);
if (ret != TD_SUCCESS) {
(td_void)drv_log_remove_module(mod_id);
/* use log info debug, beacuse of the module number is larger than register so some module id we cannot find. */
soc_log_info("invaild or do not register module id :%d \n", mod_id);
return;
}
ret = drv_log_add_module(module_data.name, mod_id);
if (ret != TD_SUCCESS) {
soc_log_info("add module failed. mod_id:%d, name :%s\n", module_data.name, mod_id);
}
}
/* TD_TRUE: need print; TD_FALSE: not print */
static td_void log_level_check(td_u32 level, td_u32 mod_id, log_level_t *log_level)
{
td_u8 current_level;
if (mod_id >= (LOG_CFG_BUF_SIZE / sizeof(log_cfg_info))) {
soc_print("mod_id invalid !\n");
return;
}
/* log module has initialized yet */
if (likely(g_log_init)) {
log_level->bbox_level = (level == SOC_LOG_LEVEL_ALERT) ? (TD_TRUE) : (TD_FALSE);
current_level = g_log_cfg_info[mod_id].log_level;
if (current_level == SOC_LOG_LEVEL_TRACE) {
log_level->general_level = (level == SOC_LOG_LEVEL_TRACE) ? (TD_TRUE) : (TD_FALSE);
log_level->memory_level = log_level->general_level;
return;
}
if (likely(current_level <= g_default_log_level)) {
if (likely(level > SOC_LOG_LEVEL_INFO)) {
return;
}
if (level <= current_level) {
log_level->memory_level = TD_TRUE;
log_level->general_level = TD_TRUE;
}
} else {
if (level <= current_level) {
log_level->general_level = TD_TRUE;
log_level->memory_level = TD_TRUE;
}
}
} else {
/* log module has not initialized yet */
if (level <= g_default_log_level) {
log_level->general_level = TD_TRUE;
log_level->memory_level = TD_TRUE;
}
}
return;
}
/* 0: seria port, 1: network */
static td_u32 drv_log_get_print_pos(td_u32 mod_id)
{
td_u32 pos;
if (mod_id >= LOG_CFG_BUF_SIZE / sizeof(log_cfg_info)) {
return LOG_OUTPUT_SERIAL;
}
if (g_log_init == TD_FALSE) {
return LOG_OUTPUT_SERIAL;
}
if (g_set_log_file_flag == TD_TRUE) {
pos = LOG_OUTPUT_UDISK;
} else {
pos = g_log_cfg_info[mod_id].log_print_pos;
}
return pos;
}
#ifdef CONFIG_SOCT_LOG_UDISK_SUPPORT
td_s32 drv_log_udisk_save(const td_s8 *file_name, const td_s8 *data, td_u32 data_len)
{
td_s32 write_len, ret;
void *file = NULL;
errno_t err_ret;
static td_char cur_file_name[LOG_MAX_FILE_NAME_LENTH] = {0};
if (file_name == TD_NULL) {
soc_log_err("file_name is null\n");
return TD_FAILURE;
}
if (strlen(file_name) < strlen(cur_file_name)) {
err_ret = memset_s(cur_file_name, LOG_MAX_FILE_NAME_LENTH, 0, sizeof(cur_file_name));
if (err_ret != EOK) {
soc_log_err("secure func call error\n");
return TD_FAILURE;
}
}
if (g_log_write_len_count > g_default_log_size) {
g_log_file_count++;
g_log_file_count = (g_log_file_count > LOG_MAX_FILE_CNT) ? (0) : (g_log_file_count);
}
ret = snprintf_s(cur_file_name, LOG_MAX_FILE_NAME_LENTH, LOG_MAX_FILE_NAME_LENTH - 1,
"%s.%d", file_name, g_log_file_count);
if (ret < 0) {
soc_log_err("call snprintf_s failed.\n");
return TD_FAILURE;
}
if (g_log_write_len_count > g_default_log_size) {
file = osal_klib_fopen(cur_file_name, OSAL_O_RDWR | OSAL_O_CREAT | OSAL_O_TRUNC, 0644); /* 0644 is authority */
if (file == NULL) {
soc_log_err("osal_klib_fopen %s failure...................\n", cur_file_name);
return TD_FAILURE;
}
osal_klib_fclose(file);
g_log_write_len_count = 0;
}
file = osal_klib_fopen(cur_file_name, OSAL_O_RDWR | OSAL_O_CREAT | OSAL_O_APPEND, 0644); /* 0644 is authority */
if (file == NULL) {
soc_log_err("osal_klib_fopen %s failure...................\n", cur_file_name);
return TD_FAILURE;
}
write_len = osal_klib_fwrite(data, data_len, file);
g_log_write_len_count += (unsigned int)write_len;
osal_klib_fclose(file);
return TD_SUCCESS;
}
static osal_task *g_udisk_task = TD_NULL;
static td_u8 g_udisk_buf[LOG_MSG_BUF_RESERVE] = {0};
static td_u8 g_udisk_file_name[LOG_MAX_FILE_NAME_LENTH] = {0};
td_s32 drv_log_udisk_write_thread(td_void *arg)
{
td_u32 read_len = 0;
td_s32 ret;
td_bool set_file_flag;
td_bool status = TD_FALSE;
errno_t err_ret;
td_u8 *udisk_log_file = (td_u8 *)arg;
if (udisk_log_file == TD_NULL) {
soc_log_err("input arg udisk_log_file is NULL.. \n");
return TD_FAILURE;
}
ret = snprintf_s(g_udisk_file_name, sizeof(g_udisk_file_name),
sizeof(g_udisk_file_name) - 1, "%s/stb.log", (const td_s8*)udisk_log_file);
if (ret < 0 ||
(strlen(g_udisk_file_name) - strlen("stb.log")) < 0 ||
strncmp(g_udisk_file_name + (strlen(g_udisk_file_name) - strlen("stb.log")),
"stb.log", strlen("stb.log")) != 0) {
soc_log_err("snprintf_s fail or file_name invalid [%s]!\n", g_udisk_file_name);
return TD_FAILURE;
}
while (1) {
set_file_flag = g_set_log_file_flag;
set_current_state(TASK_INTERRUPTIBLE);
if (osal_kthread_should_stop()) {
break;
}
if (set_file_flag == TD_FALSE) {
osal_msleep(10); /* 10ms polling */
continue;
}
ret = log_store_lock();
err_ret = memset_s(g_udisk_buf, sizeof(g_udisk_buf), 0, sizeof(g_udisk_buf));
if (err_ret != EOK) {
soc_log_err("secure func call error\n");
log_store_unlock();
return TD_FAILURE;
}
ret = ext_drv_log_read_buf(g_udisk_buf, sizeof(g_udisk_buf) - 1, &read_len, &status, TD_TRUE);
if (ret == TD_SUCCESS) {
drv_log_udisk_save((const td_s8 *)g_udisk_file_name, g_udisk_buf, read_len);
soc_log_info("b_status = %d\n", status);
}
log_store_unlock();
osal_msleep(10); /* save log every 10ms */
}
return TD_SUCCESS;
}
td_s32 drv_log_udisk_init(const td_u8 *disk_folder)
{
if (disk_folder == TD_NULL) {
return TD_FAILURE;
}
if (g_udisk_task == TD_NULL) {
g_udisk_task = osal_kthread_create(drv_log_udisk_write_thread, (td_void *)disk_folder, "g_udisk_task", 0);
if (g_udisk_task == TD_NULL) {
soc_log_err("create new kernel thread failed\n");
return TD_FAILURE;
}
}
return TD_SUCCESS;
}
td_s32 drv_log_udisk_exit(td_void)
{
if (g_udisk_task != TD_NULL) {
osal_kthread_destroy(g_udisk_task, TD_TRUE);
g_udisk_task = TD_NULL;
}
return TD_SUCCESS;
}
#endif
td_void soc_log_simple_print(const td_char *format, ...)
{
va_list args;
td_u32 msg_len;
td_char log_str[LOG_MAX_TRACE_LEN] = {'a'};
log_str[LOG_MAX_TRACE_LEN - 0x1] = 'b';
log_str[LOG_MAX_TRACE_LEN - 0x2] = 'c';
va_start(args, format);
msg_len = (td_u32)vsnprintf_s(log_str, sizeof(log_str), LOG_MAX_TRACE_LEN - 1, format, args);
va_end(args);
if (msg_len < 0) {
return;
}
if (msg_len >= LOG_MAX_TRACE_LEN) {
log_str[LOG_MAX_TRACE_LEN - 0x1] = '\0'; /* even the 'vsnprintf' commond will do it */
log_str[LOG_MAX_TRACE_LEN - 0x2] = '\n';
log_str[LOG_MAX_TRACE_LEN - 0x3] = '.';
log_str[LOG_MAX_TRACE_LEN - 0x4] = '.';
log_str[LOG_MAX_TRACE_LEN - 0x5] = '.';
}
soc_print("%s", log_str);
}
td_void soc_log_print_block(td_u32 level, td_u32 module_id, const td_char *block, td_u32 size)
{
errno_t err_ret;
td_s32 ret;
td_u32 i;
td_char str_out[LOG_BLOCK_BUFSIZE] = {0};
if (block == NULL) {
return;
}
for (i = 0; i < size; i++) {
ret = snprintf_s(&str_out[(i % LOG_BLOCK_PERLINE) * 3], /* 3 is offset */
(LOG_BLOCK_BUFSIZE - (i % LOG_BLOCK_PERLINE) * 3), 4, " %02X", block[i]); /* 4,3 is countsize */
if (ret == -1) {
soc_print("snprintf_s failed!!!");
return;
}
if (((i + 1) % LOG_BLOCK_PERLINE) == 0) {
soc_trace(level, module_id, " %s\n", str_out);
err_ret = memset_s(str_out, sizeof(str_out), 0x00, sizeof(str_out));
if (err_ret != EOK) {
soc_print("memset_s failed!!!");
return;
}
}
}
if (((i % LOG_BLOCK_PERLINE) != 0) && (i != 0)) {
soc_trace(level, module_id, " %s\n", str_out);
}
}
static td_void drv_log_adjust_str(char *log_str, td_u32 str_len, td_u32 log_cnt)
{
if ((log_str != TD_NULL) && (unlikely(log_cnt >= str_len))) {
log_str[LOG_MAX_TRACE_LEN - 1] = '\0'; /* even the 'vsnprintf' commond will do it */
log_str[LOG_MAX_TRACE_LEN - 2] = '\n'; /* 2 表示log_str向左偏移2个字节 */
log_str[LOG_MAX_TRACE_LEN - 3] = '.'; /* 3 表示log_str向左偏移3个字节 */
log_str[LOG_MAX_TRACE_LEN - 4] = '.'; /* 4 表示log_str向左偏移4个字节 */
log_str[LOG_MAX_TRACE_LEN - 5] = '.'; /* 5 表示log_str向左偏移5个字节 */
log_cnt = LOG_MAX_TRACE_LEN;
}
return;
}
static td_void drv_log_print(soc_mod_id mod_id, log_level_t *log_level,
char *log_str, td_u32 str_len, td_u32 log_cnt)
{
td_u32 n_pos;
if (log_level->bbox_level == TD_TRUE) {
log_get_rtc_time(log_str, str_len);
rdr_print_to_file("%s", log_str);
return;
}
n_pos = drv_log_get_print_pos(mod_id);
switch (n_pos) {
case LOG_OUTPUT_SERIAL:
if ((mod_id == SOC_ID_VSYNC) || (mod_id == SOC_ID_ASYNC)) {
break;
}
if (g_log_store_info.store_log_enable == TD_TRUE && log_level->memory_level == TD_TRUE) {
log_get_rtc_time(log_str, str_len);
ext_drv_log_write_buf((td_u8 *)log_str, log_cnt, LOG_MSG_FROM_KERNEL);
}
if (log_level->general_level == TD_TRUE) {
log_get_rtc_time(log_str, str_len);
soc_print("%s", log_str);
}
break;
case LOG_OUTPUT_NETWORK:
case LOG_OUTPUT_UDISK:
#if defined(CONFIG_SOCT_LOG_NETWORK_SUPPORT) || defined(CONFIG_SOCT_LOG_UDISK_SUPPORT)
if (log_level->general_level == TD_TRUE) {
log_get_rtc_time(log_str, str_len);
ext_drv_log_write_buf((td_u8 *)log_str, log_cnt, LOG_MSG_FROM_KERNEL);
}
#endif
break;
default:
soc_print("output pos %d invalid!\n", n_pos);
}
return;
}
static td_u32 soc_log_print_msg_process(char *log_serial, td_u32 level,
td_u32 mod_id, const td_u8 *fn_name, td_u32 line_num)
{
td_s32 msg_len = 0;
td_u32 buff_len = LOG_MAX_TRACE_LEN - LOG_RTC_TIME_LENGH;
if (log_serial == NULL || fn_name == NULL) {
soc_print("soc_log_print_msg_process input null\n");
return 0;
}
if (likely(g_log_init)) {
msg_len = snprintf_s(log_serial, buff_len, buff_len - 1,
"[%s-%s]:%s[%d]:", g_debug_level_name[level], g_log_cfg_info[mod_id].module_name, fn_name, line_num);
if (msg_len < 0) {
soc_print("soc_log_print_msg_process snprintf_s --failed\n");
return 0;
}
}
return (td_u32)msg_len;
}
td_void soc_log_print(td_u32 level, td_u32 mod_id, const td_u8 *fn_name, td_u32 line_num,
const td_char *format, ...)
{
va_list args;
td_u32 msg_len;
char log_str[LOG_MAX_TRACE_LEN] = {'a'};
td_u32 log_cnt = LOG_RTC_TIME_LENGH;
char *log_serial = log_str + LOG_RTC_TIME_LENGH;
char *log_msg_pos = TD_NULL;
td_u32 buff_len = LOG_MAX_TRACE_LEN - LOG_RTC_TIME_LENGH;
log_level_t log_level = { TD_FALSE, TD_FALSE, TD_FALSE };
if ((level > SOC_LOG_LEVEL_MAX) ||
(mod_id >= (LOG_CFG_BUF_SIZE / sizeof(log_cfg_info))) ||
(fn_name == TD_NULL)) {
soc_print("ERR: invalid param, level:%#x, mod_id:%#x, fn_name:%p\n", level, mod_id, fn_name);
return;
}
log_level_check(level, mod_id, &log_level);
if (unlikely(log_level.memory_level == TD_TRUE || log_level.general_level == TD_TRUE)) {
msg_len = soc_log_print_msg_process(log_serial, level, mod_id, fn_name, line_num);
log_cnt += msg_len;
log_str[LOG_MAX_TRACE_LEN - 1] = 'b';
log_str[LOG_MAX_TRACE_LEN - 2] = 'c'; /* 2 表示log_str向左偏移2个字节 */
if (likely(buff_len > msg_len)) {
log_msg_pos = log_serial + msg_len;
buff_len = buff_len - msg_len;
va_start(args, format);
msg_len = (td_u32)vsnprintf_s(log_msg_pos, buff_len, buff_len - 1, format, args);
if (msg_len < 0) {
va_end(args);
return;
}
va_end(args);
log_cnt += msg_len;
}
drv_log_adjust_str(log_str, LOG_MAX_TRACE_LEN, log_cnt);
if (unlikely(g_log_init == 0)) {
/* log module has not Initialized. */
soc_print("[%s-Unknow]: %s[%d]:%s", g_debug_level_name[level], fn_name, line_num, log_msg_pos);
return;
}
/* log module has initialized. */
drv_log_print(mod_id, &log_level, log_str, LOG_MAX_TRACE_LEN, log_cnt);
}
return;
}
td_s32 drv_log_set_path(const td_char *path, td_u32 path_len, td_bool is_user_state)
{
td_s32 ret;
if (path == TD_NULL || path_len >= sizeof(g_log_path_buf)) {
return TD_FAILURE;
}
ret = log_file_lock();
if (ret != 0) {
soc_log_err("down_interruptible failed\n");
return TD_FAILURE;
}
(td_void)memset_s(g_log_path_buf, sizeof(g_log_path_buf), 0, sizeof(g_log_path_buf));
if (is_user_state == TD_TRUE) {
ret = (td_s32)osal_copy_from_user(g_log_path_buf, path, path_len);
} else {
ret = memcpy_s(g_log_path_buf, sizeof(g_log_path_buf), path, path_len);
}
if (ret != 0) {
log_file_unlock();
return TD_FAILURE;
}
if (memcmp(g_log_path_buf, "/dev/null", strlen("/dev/null")) == 0) {
g_set_log_file_flag = TD_FALSE;
} else {
g_set_log_file_flag = TD_TRUE;
}
g_log_cfg_info->udisk_flag = (td_u8)g_set_log_file_flag;
g_udisk_log_file = g_log_path_buf;
log_file_unlock();
return TD_SUCCESS;
}
td_s32 ext_drv_log_get_path(td_s8 *buf, td_u32 buf_len)
{
td_u32 path_len;
td_s32 ret;
/* not support log when uart close or user version */
#if defined (CONFIG_CLOSE_UART0) || defined (ANDROID_BUILD_USER)
return TD_SUCCESS;
#endif
if (osal_get_buildvariant() == OSAL_BUILDVARIANT_USER) {
return TD_SUCCESS;
}
if (g_udisk_log_file == TD_NULL) {
soc_log_err("g_udisk_log_file is NULL!\n");
return TD_FAILURE;
}
if (buf == TD_NULL) {
soc_log_err("buf is NULL!\n");
return TD_FAILURE;
}
path_len = strlen(g_udisk_log_file) + 1;
if (path_len > buf_len) {
soc_log_err("path len is lager than buf len!\n");
return TD_FAILURE;
}
if (path_len == 1) {
soc_log_info("no redirect to file!\n");
return TD_SUCCESS;
}
ret = memcpy_s(buf, buf_len, g_udisk_log_file, path_len);
if (ret != EOK) {
soc_log_err("memcpy_s fail\n");
return TD_FAILURE;
}
return TD_SUCCESS;
}
td_s32 drv_log_set_store_path(const td_char *path, td_u32 path_len, td_bool is_user_state)
{
td_s32 ret;
/* not support log when uart close or user version */
#if defined (CONFIG_CLOSE_UART0) || defined (ANDROID_BUILD_USER)
return TD_SUCCESS;
#endif
if (osal_get_buildvariant() == OSAL_BUILDVARIANT_USER) {
return TD_SUCCESS;
}
if (path == TD_NULL || path_len >= sizeof(g_store_path_buf)) {
return TD_FAILURE;
}
ret = log_file_lock();
if (ret != 0) {
soc_log_err("down_interruptible failed\n");
return TD_FAILURE;
}
(td_void)memset_s(g_store_path_buf, sizeof(g_store_path_buf), 0, sizeof(g_store_path_buf));
if (is_user_state == TD_TRUE) {
ret = (td_s32)osal_copy_from_user(g_store_path_buf, path, path_len);
} else {
ret = memcpy_s(g_store_path_buf, sizeof(g_store_path_buf), path, path_len);
}
if (ret != 0) {
log_file_unlock();
return TD_FAILURE;
}
g_store_path = g_store_path_buf;
log_file_unlock();
return TD_SUCCESS;
}
td_s32 ext_drv_log_get_store_path(td_s8 *buf, td_u32 buf_len)
{
td_u32 path_len;
td_s32 ret;
if (g_store_path == TD_NULL || buf == TD_NULL) {
return TD_FAILURE;
}
path_len = strlen(g_store_path) + 1;
if (path_len > buf_len || path_len <= 1) {
return TD_FAILURE;
}
ret = memcpy_s(buf, buf_len, g_store_path, path_len);
if (ret != EOK) {
return TD_FAILURE;
}
return TD_SUCCESS;
}
td_s32 ext_drv_log_set_size(td_u32 size)
{
td_s32 ret;
if (size > LOG_MAX_FILE_SIZE || size < LOG_MIN_FILE_SIZE) {
soc_log_err("Logsize(%dMB) is out of range(%dMB~%dMB)\n", size, LOG_MIN_FILE_SIZE, LOG_MAX_FILE_SIZE);
return TD_FAILURE;
}
ret = log_file_lock();
if (ret != 0) {
soc_log_err("down_interruptible failed\n");
return TD_FAILURE;
}
g_default_log_size = size * 1024 * 1024; /* 1024 * 1024 means 1k */
log_file_unlock();
soc_log_info("set log file size as %d MB\n", g_default_log_size);
return TD_SUCCESS;
}
td_s32 ext_drv_log_get_level(td_u32 mod_id, soc_log_level *log_level)
{
if (g_log_init == TD_FALSE || mod_id >= LOG_CFG_BUF_SIZE / sizeof(log_cfg_info) || log_level == TD_NULL) {
return TD_FAILURE;
}
*log_level = (soc_log_level)g_log_cfg_info[mod_id].log_level;
return TD_SUCCESS;
}
static td_s32 drv_log_cfg_info_init(td_void)
{
td_u32 i;
td_s32 ret;
g_log_cfg_buf.dmabuf = osal_mem_alloc("CMN_LogInfo", LOG_CFG_BUF_SIZE, OSAL_MMZ_TYPE, TD_NULL, 0);
if (IS_ERR_OR_NULL(g_log_cfg_buf.dmabuf)) {
soc_log_err("osal_mem_alloc failed!\n");
return TD_FAILURE;
}
g_log_cfg_buf.virt_addr = (td_u8 *)osal_mem_kmap(g_log_cfg_buf.dmabuf, 0, TD_FALSE);
if (IS_ERR_OR_NULL(g_log_cfg_buf.virt_addr)) {
osal_mem_free(g_log_cfg_buf.dmabuf);
soc_log_err("dma_buf_kmap failed!\n");
return TD_FAILURE;
}
osal_mem_flush(g_log_cfg_buf.dmabuf);
ret = memset_s(g_log_cfg_buf.virt_addr, LOG_CFG_BUF_SIZE, 0, LOG_CFG_BUF_SIZE);
if (ret != EOK) {
osal_mem_free(g_log_cfg_buf.dmabuf);
soc_log_err("memset_s error!\n");
return TD_FAILURE;
}
g_log_cfg_info = (log_cfg_info *)g_log_cfg_buf.virt_addr;
g_log_cfg_info->udisk_flag = 0;
/* max debug module number: 8192/28 = 341/292 */
for (i = 0; i < LOG_CFG_BUF_SIZE / sizeof(log_cfg_info); i++) {
g_log_cfg_info[i].log_level = (td_u8)g_default_log_level;
g_log_cfg_info[i].log_print_pos = LOG_OUTPUT_SERIAL;
g_log_cfg_info[i].log_quota = DEFAULT_LOG_QUOTA;
ret = snprintf_s(g_log_cfg_info[i].module_name, sizeof(g_log_cfg_info[i].module_name),
sizeof(g_log_cfg_info[i].module_name) - 1, "Invalid");
if (ret < 0) {
osal_mem_free(g_log_cfg_buf.dmabuf);
soc_log_err("snprintf_s error!\n");
return TD_FAILURE;
}
}
return TD_SUCCESS;
}
static td_s32 drv_log_cfg_info_exit(td_void)
{
if (g_log_cfg_buf.virt_addr != 0) {
osal_mem_kunmap(g_log_cfg_buf.dmabuf, (td_void *)g_log_cfg_buf.virt_addr, 0);
osal_mem_free(g_log_cfg_buf.dmabuf);
g_log_cfg_info = TD_NULL;
}
return TD_SUCCESS;
}
#if defined(CONFIG_SOCT_LOG_NETWORK_SUPPORT) || defined(CONFIG_SOCT_LOG_UDISK_SUPPORT)
static td_s32 drv_log_buf_init(td_u32 size)
{
(td_void)memset_s(&g_log_msg_info, sizeof(g_log_msg_info), 0, sizeof(g_log_msg_info));
g_log_msg_info.buf_size = size;
osal_wait_init(&g_log_msg_info.wq_no_data);
g_log_msg_buf.dmabuf = osal_mem_alloc("CMN_LogTrace", size, OSAL_MMZ_TYPE, TD_NULL, 0);
if (IS_ERR_OR_NULL(g_log_msg_buf.dmabuf)) {
soc_log_err("ion_alloc_dmabuf failed!\n");
osal_wait_destroy(&g_log_msg_info.wq_no_data);
return TD_FAILURE;
}
g_log_msg_buf.virt_addr = (td_u8 *)osal_mem_kmap(g_log_msg_buf.dmabuf, 0, TD_FALSE);
if (IS_ERR_OR_NULL(g_log_msg_buf.virt_addr)) {
soc_log_err("dma_buf_kmap failed!\n");
osal_mem_free(g_log_msg_buf.dmabuf);
osal_wait_destroy(&g_log_msg_info.wq_no_data);
return TD_FAILURE;
}
(td_void)memset_s(g_log_msg_buf.virt_addr, size, 0, size);
g_log_msg_info.start_virt_addr = g_log_msg_buf.virt_addr;
return TD_SUCCESS;
}
static td_s32 drv_log_buf_exit(td_void)
{
if (g_log_msg_buf.virt_addr != TD_NULL) {
osal_mem_kunmap(g_log_msg_buf.dmabuf, (td_void *)g_log_msg_buf.virt_addr, 0);
osal_mem_free(g_log_msg_buf.dmabuf);
osal_wait_destroy(&g_log_msg_info.wq_no_data);
g_log_msg_info.start_virt_addr = TD_NULL;
}
return TD_SUCCESS;
}
#endif
static td_s32 drv_log_get_cfg_buf_fd(td_mem_handle_t *fd)
{
td_s32 ret = TD_FAILURE;
td_mem_handle_t buf_fd;
td_u32 idx;
td_u32 module_num = LOG_CFG_BUF_SIZE / sizeof(log_cfg_info);
/* process register module log feature */
for (idx = 0; idx < module_num; idx++) {
drv_log_set_module(idx);
}
if (g_log_init == TD_TRUE && g_log_cfg_buf.dmabuf != TD_NULL) {
buf_fd = osal_mem_create_fd(g_log_cfg_buf.dmabuf, O_CLOEXEC);
if (buf_fd < 0) {
soc_log_err("ext_dma_buf_fd failed!\n");
*fd = 0;
} else {
*fd = buf_fd;
ret = TD_SUCCESS;
}
} else {
soc_log_err("Log is not init!\n");
*fd = 0;
}
return ret;
}
static td_s32 drv_log_put_cfg_buf_fd(td_mem_handle_t fd)
{
if (fd < 0) {
soc_log_err("invalid fd!\n");
return TD_FAILURE;
}
osal_mem_close_fd((long)fd);
return TD_SUCCESS;
}
td_s32 drv_log_init(td_void)
{
#if defined(CONFIG_SOCT_LOG_NETWORK_SUPPORT) || defined(CONFIG_SOCT_LOG_UDISK_SUPPORT)
ext_chip_name_id chip_name_id;
#endif
osal_dts_get_u32_byname("huanglong,common", "log_level", &g_default_log_level);
if (drv_log_cfg_info_init() != TD_SUCCESS) {
return TD_FAILURE;
}
#if defined(CONFIG_SOCT_LOG_NETWORK_SUPPORT) || defined(CONFIG_SOCT_LOG_UDISK_SUPPORT)
ext_drv_sys_get_chip_name_id(&chip_name_id);
/* on reserved5, MMZ size is only 8M, therfore, the size of log MMZ reduce to 512K */
if ((chip_name_id == CHIP_NAME_RESERVED5) || (chip_name_id == CHIP_NAME_RESERVED2)) {
g_log_buf_size = 0x80 * LOG_MSG_BUF_RESERVE;
} else if ((chip_name_id == CHIP_NAME_RESERVED13) || (chip_name_id == CHIP_NAME_RESERVED9) ||
(chip_name_id == CHIP_NAME_RESERVED6) || (chip_name_id == CHIP_NAME_RESERVED8)) {
g_log_buf_size = 0xa * 0x100 * LOG_MSG_BUF_RESERVE; /* 10M buf size for NPU save log */
} else {
soc_log_info("unspport chip_type chip_version, g_log_bu_size use default value 10M. \n");
g_log_buf_size = LOG_MSG_BUF_RESERVE;
}
if (drv_log_buf_init(g_log_buf_size) != TD_SUCCESS) {
drv_log_cfg_info_exit();
return TD_FAILURE;
}
#endif
if (drv_log_add_module("ASYNC", (td_u32)SOC_ID_ASYNC) != TD_SUCCESS) {
#if defined(CONFIG_SOCT_LOG_NETWORK_SUPPORT) || defined(CONFIG_SOCT_LOG_UDISK_SUPPORT)
drv_log_buf_exit();
#endif
drv_log_cfg_info_exit();
return TD_FAILURE;
}
if (drv_log_add_module("VSYNC", (td_u32)SOC_ID_VSYNC) != TD_SUCCESS) {
drv_log_remove_module((td_u32)SOC_ID_ASYNC);
#if defined(CONFIG_SOCT_LOG_NETWORK_SUPPORT) || defined(CONFIG_SOCT_LOG_UDISK_SUPPORT)
drv_log_buf_exit();
#endif
drv_log_cfg_info_exit();
return TD_FAILURE;
}
g_log_init = TD_TRUE;
osal_sem_init(&g_log_k_mutex, 1);
osal_sem_init(&g_log_store_mutex, 1);
osal_wait_init(&g_log_store_info.poll_wait_queue);
osal_klib_set_store_path(g_store_path);
return TD_SUCCESS;
}
td_void drv_log_exit(td_void)
{
g_log_init = TD_FALSE;
osal_sem_destroy(&g_log_k_mutex);
osal_sem_destroy(&g_log_store_mutex);
osal_wait_destroy(&g_log_store_info.poll_wait_queue);
#ifdef CONFIG_SOCT_LOG_UDISK_SUPPORT
if (drv_log_udisk_exit() != TD_SUCCESS) {
soc_log_err("drv_log_udisk_exit error!\n");
return;
}
#endif
#if defined(CONFIG_SOCT_LOG_NETWORK_SUPPORT) || defined(CONFIG_SOCT_LOG_UDISK_SUPPORT)
if (drv_log_buf_exit() != TD_SUCCESS) {
soc_log_err("drv_log_buf_exit error!\n");
return;
}
#endif
if (drv_log_cfg_info_exit() != TD_SUCCESS) {
soc_log_err("drv_log_cfg_info_exit error!\n");
return;
}
}
#ifndef MODULE
/* Legacy boot options - nonmodular */
static td_s32 __init drv_log_get_buf_size(td_char *str)
{
g_log_buf_size = simple_strtol(str, TD_NULL, 0);
soc_log_info("g_log_buf_size = 0x%x\n", g_log_buf_size);
return 1;
}
__setup("g_log_buf_size=", drv_log_get_buf_size);
#endif
EXPORT_SYMBOL(ext_drv_log_read_buf);
EXPORT_SYMBOL(ext_drv_log_write_buf);
EXPORT_SYMBOL(ext_drv_log_get_store_path);
EXPORT_SYMBOL(ext_drv_log_get_level);
EXPORT_SYMBOL(soc_log_print);
EXPORT_SYMBOL(soc_log_print_block);
EXPORT_SYMBOL(soc_log_simple_print);
#ifdef MODULE
module_param(g_log_buf_size, int, S_IRUGO);
module_param(g_udisk_log_file, charp, S_IRUGO);
module_param(g_store_path, charp, S_IRUGO);
EXPORT_SYMBOL(g_store_path);
#endif
static td_s32 drv_log_find_module(const td_char *s)
{
td_u32 i;
td_u32 cnt = LOG_CFG_BUF_SIZE / sizeof(log_cfg_info);
for (i = 0; i < cnt; i++) {
if (!strncasecmp(g_log_cfg_info[i].module_name, s, sizeof(g_log_cfg_info[i].module_name))) {
return i;
}
}
return -1;
}
static td_s32 drv_log_process_proc_help(td_u32 argc, td_char(*argv)[PROC_CMD_SINGEL_LENGTH_MAX],
td_void *private)
{
if (g_log_init == TD_FALSE) {
soc_log_err("Log is not init!\n");
return TD_FAILURE;
}
osal_proc_echo("\n=========================================================log"
"=============================================================================================\n");
osal_proc_echo("echo command para1 para2 path "
"explanation\n");
osal_proc_echo("echo loglevel SOC_DEMUX 2 >/proc/msp/log "
"modify the log level of the SOC_DEMUX to 2\n");
osal_proc_echo(" "
"para1(module_name) para2(0:ALERT 1:FATAL 2:ERROR WARN:3 NOTICE:4 INFO:5 DEBUG:6 TRACE:7)\n");
osal_proc_echo("echo loglevel all 2 >/proc/msp/log "
"modify the log level of all module to 2\n");
osal_proc_echo(" "
"para1(module_name) para2(0:ALERT 1:FATAL 2:ERROR WARN:3 NOTICE:4 INFO:5 DEBUG:6 TRACE:7)\n");
osal_proc_echo("echo logsize 12 >/proc/msp/log "
"set log size as 12 MB para1(1M~120MB)\n");
osal_proc_echo("echo logpath /tmp >/proc/msp/log "
"set log path as /tmp para1(log path)\n");
osal_proc_echo("echo logpath /dev/null >/proc/msp/log "
"close log udisk output para1(log path)\n");
osal_proc_echo("echo storepath /mnt >/proc/msp/log "
"set the debug file store path as /mnt para1(store path)\n");
osal_proc_echo("============================================================"
"=============================================================================================\n");
return TD_SUCCESS;
}
static td_s32 drv_log_process_proc_level(td_u32 argc, td_char(*argv)[PROC_CMD_SINGEL_LENGTH_MAX],
td_void *private)
{
td_char *module = TD_NULL;
td_u8 level;
td_s32 idx;
td_u32 module_num = LOG_CFG_BUF_SIZE / sizeof(log_cfg_info);
if (g_log_init == TD_FALSE) {
soc_log_err("Log is not init!\n");
return TD_FAILURE;
}
if (argc != 3) { /* the number of required paras is 3 */
soc_log_err("argc is invalid!\n");
return TD_FAILURE;
}
module = argv[1]; /* the first para(1) is module name */
level = argv[2][0] - '0'; /* the second para(2) is log level */
if (level >= SOC_LOG_LEVEL_MAX) {
soc_log_err("level is invalid!\n");
return TD_FAILURE;
}
if (!strncasecmp("all", module, sizeof("all"))) {
for (idx = 0; idx < module_num; idx++) {
g_log_cfg_info[idx].log_level = level;
}
return TD_SUCCESS;
}
idx = drv_log_find_module(module);
if (idx == -1) {
soc_log_err("%s is not registered!\n", module);
return TD_FAILURE;
}
g_log_cfg_info[idx].log_level = level;
return TD_SUCCESS;
}
static td_s32 drv_log_process_proc_size(td_u32 argc, td_char(*argv)[PROC_CMD_SINGEL_LENGTH_MAX],
td_void *private)
{
td_u32 log_size;
if (g_log_init == TD_FALSE) {
soc_log_err("Log is not init!\n");
return TD_FAILURE;
}
if (argc != 2) { /* the number of required paras is 2 */
soc_log_err("argc is invalid!\n");
return TD_FAILURE;
}
if (strstr(argv[1], "0x") || strstr(argv[1], "0X")) {
log_size = simple_strtoul(argv[1], TD_NULL, 16); /* the first para(1) is log size, 16 base conversion */
} else {
log_size = simple_strtoul(argv[1], TD_NULL, 10); /* the first para(1) is log size, 10 base conversion */
}
if (log_size > LOG_MAX_FILE_SIZE || log_size < LOG_MIN_FILE_SIZE) {
soc_log_err("size is invalid!\n");
return TD_FAILURE;
}
return ext_drv_log_set_size(log_size);
}
td_s32 log_drv_udisk_store_init(td_void)
{
#ifdef CONFIG_SOCT_LOG_UDISK_SUPPORT
td_s32 ret;
ret = drv_log_udisk_init(g_udisk_log_file);
if (ret != TD_SUCCESS) {
soc_log_err("call log_udisk_init failed!\n");
return TD_FAILURE;
}
#endif
return TD_SUCCESS;
}
td_s32 log_drv_udisk_store_deinit(td_void)
{
#ifdef CONFIG_SOCT_LOG_UDISK_SUPPORT
td_s32 ret;
g_log_cfg_info->udisk_flag = (td_u8)g_set_log_file_flag;
soc_log_info("set log path is g_log_path_buf = %s\n", g_udisk_log_file);
ret = drv_log_udisk_exit();
if (ret != TD_SUCCESS) {
soc_log_err("call drv_log_udisk_exit failed!\n");
return TD_FAILURE;
}
#endif
return TD_SUCCESS;
}
static td_s32 drv_log_process_proc_path(td_u32 argc, td_char(*argv)[PROC_CMD_SINGEL_LENGTH_MAX],
td_void *private)
{
td_s32 ret;
errno_t err_ret;
if (argc < 2) { /* argc at least 2 */
soc_log_err("param invalid! argc = %d\n", argc);
return TD_FAILURE;
}
if (strlen(argv[1]) >= sizeof(g_log_path_buf)) { /* 命令的第1个参数 */
soc_log_err("log path length is over than %d!\n", sizeof(g_log_path_buf));
return TD_FAILURE;
}
ret = log_file_lock();
if (ret != 0) {
soc_log_err("down_interruptible failed\n");
return TD_FAILURE;
}
err_ret = memcpy_s(g_log_path_buf, LOG_MAX_FILE_NAME_LENTH, argv[1], strlen(argv[1]) + 1); /* 命令的第1个参数 */
if (err_ret != EOK) {
log_file_unlock();
soc_log_err("secure func call error\n");
return TD_FAILURE;
}
g_udisk_log_file = g_log_path_buf;
if (memcmp(g_log_path_buf, "/dev/null", strlen("/dev/null")) != 0) {
ret = log_drv_udisk_store_init();
if (ret != TD_SUCCESS) {
log_file_unlock();
soc_log_err("log_drv_udisk_store_init failed ... \n");
return ret;
}
g_set_log_file_flag = TD_TRUE;
if (g_log_store_info.store_log_thread_exist == TD_TRUE) {
g_log_store_info.store_log_enable = TD_FALSE;
}
} else {
g_set_log_file_flag = TD_FALSE;
if (g_log_store_info.store_log_thread_exist == TD_TRUE) {
g_log_store_info.store_log_enable = TD_TRUE;
}
ret = log_drv_udisk_store_deinit();
log_file_unlock();
return ret;
}
g_log_cfg_info->udisk_flag = (td_u8)g_set_log_file_flag;
log_file_unlock();
soc_log_info("set log path is g_log_path_buf = %s\n", g_udisk_log_file);
return TD_SUCCESS;
}
static td_s32 drv_log_process_proc_store_path(td_u32 argc, td_char(*argv)[PROC_CMD_SINGEL_LENGTH_MAX],
td_void *private)
{
errno_t err_ret;
if (argc < 2) { /* argc at least 2 */
soc_log_err("param invalid! argc = %d\n", argc);
return TD_FAILURE;
}
if (strlen(argv[1]) >= sizeof(g_store_path_buf)) { /* 命令的第1个参数 */
soc_log_err("store path length is over than %d!\n", sizeof(g_store_path_buf));
return TD_FAILURE;
}
log_file_lock();
err_ret = memset_s(g_store_path_buf, LOG_MAX_FILE_NAME_LENTH, 0, sizeof(g_store_path_buf));
if (err_ret != EOK) {
log_file_unlock();
soc_log_err("secure func call error\n");
return TD_FAILURE;
}
err_ret = memcpy_s(g_store_path_buf, LOG_MAX_FILE_NAME_LENTH, argv[1], strlen(argv[1])); /* 命令的第1个参数 */
if (err_ret != EOK) {
log_file_unlock();
soc_log_err("secure func call error\n");
return TD_FAILURE;
}
g_store_path = g_store_path_buf;
log_file_unlock();
soc_log_info("set log path is store_path = %s\n", g_store_path_buf);
return TD_SUCCESS;
}
static osal_proc_cmd g_proc_cmd[] = {
{"help", drv_log_process_proc_help},
{"loglevel", drv_log_process_proc_level},
{"logsize", drv_log_process_proc_size},
{"logpath", drv_log_process_proc_path},
{"storepath", drv_log_process_proc_store_path}
};
static td_void print_loglevel_helpinfo(td_void *s)
{
td_u32 i;
osal_seq_printf(s, "------------------support_log_level -----------------\n");
osal_seq_printf(s, "loglevel |level_val |\n");
for (i = 0; i < SOC_LOG_LEVEL_MAX; i++) {
osal_seq_printf(s, "%-18s|%-33d|\n", g_debug_level_name[i], i);
}
return;
}
td_s32 drv_log_read_proc(td_void *s, td_void *arg)
{
td_u32 i;
td_u8 level;
td_char path[LOG_MAX_FILE_NAME_LENTH] = {0};
td_u32 cnt = LOG_CFG_BUF_SIZE / sizeof(log_cfg_info);
if (g_log_init == TD_FALSE) {
osal_seq_printf(s, "Log is not init!\n");
return TD_SUCCESS;
}
if (ext_drv_log_get_path(path, sizeof(path)) != TD_SUCCESS) {
soc_log_err("ext_drv_log_get_path failed!\n");
return TD_FAILURE;
}
osal_seq_printf(s, "\n[log] %s\n", VERSION_STRING);
osal_seq_printf(s, "------------------log_path---------------------------\n");
osal_seq_printf(s, "log_path :%-33s|\n", path);
if (ext_drv_log_get_store_path(path, sizeof(path)) != TD_SUCCESS) {
soc_log_err("ext_drv_log_get_store_path failed!\n");
return TD_FAILURE;
}
osal_seq_printf(s, "------------------store_path-------------------------\n");
osal_seq_printf(s, "store_path :%-33s|\n", path);
osal_seq_printf(s, "------------------Store Path-------------------------\n");
osal_seq_printf(s, "maxlogsize(MB) :%-33u|\n", (g_default_log_size / 1024U / 1024U));
osal_seq_printf(s, "------------------module_log_level-------------------\n");
osal_seq_printf(s, "Log_module |Level |\n");
for (i = 0; i < cnt; i++) {
drv_log_set_module(i);
if (strncmp(g_log_cfg_info[i].module_name, "Invalid", 0x8)) {
level = g_log_cfg_info[i].log_level;
if (level <= SOC_LOG_LEVEL_MAX) {
osal_seq_printf(s, "%-18s|%1d(%-6s) |\n", g_log_cfg_info[i].module_name,
level, g_debug_level_name[level]);
}
}
}
print_loglevel_helpinfo(s);
osal_seq_printf(s, "=====================================================\n");
return TD_SUCCESS;
}
td_s32 drv_log_add_proc(td_void)
{
osal_proc_entry *item = TD_NULL;
item = osal_proc_add(SOC_MOD_LOG_NAME, strlen(SOC_MOD_LOG_NAME));
if (item == TD_NULL) {
soc_log_err("add proc failed!\n");
return TD_FAILURE;
}
item->read = drv_log_read_proc;
item->cmd_cnt = sizeof(g_proc_cmd) / sizeof(osal_proc_cmd);
item->cmd_list = g_proc_cmd;
return TD_SUCCESS;
}
td_void drv_log_remove_proc(td_void)
{
osal_proc_remove(SOC_MOD_LOG_NAME, strlen(SOC_MOD_LOG_NAME));
}
td_s32 drv_log_network_or_udisk_read(td_u32 cmd, td_void *arg)
{
log_read_buf *para = (log_read_buf *)arg;
if (cmd != LOG_CMPI_READ) {
soc_log_err("cmd is not LOG_CMPI_READ.\n");
return TD_FAILURE;
}
if (para == TD_NULL || para->msg_addr == TD_NULL) {
soc_log_err("User buffer is null!\n");
return TD_FAILURE;
}
if (para->magic_num != LOG_MAGIC_NUM) {
soc_log_err("User buffer is likely illegal!\n");
return TD_FAILURE;
}
return ext_drv_log_read_buf(para->msg_addr, para->buf_len, &para->copy_len, &para->task_status, TD_FALSE);
}
td_s32 drv_log_network_or_udisk_write(td_u32 cmd, const td_void *arg)
{
log_write_buf *para = (log_write_buf *)arg;
if (cmd != LOG_CMPI_WRITE) {
soc_log_err("cmd is not LOG_CMPI_WRITE \n");
return TD_FAILURE;
}
if (para == TD_NULL || para->msg_addr == TD_NULL) {
soc_log_err("User buffer is null!\n");
return TD_FAILURE;
}
return ext_drv_log_write_buf(para->msg_addr, para->msg_len, LOG_MSG_FROM_USER);
}
td_s32 drv_log_ioctl(td_u32 cmd, td_void *arg, td_void *private_data)
{
if (arg == TD_NULL) {
soc_log_err("param arg invalid!\n");
return TD_FAILURE;
}
switch (cmd) {
case LOG_CMPI_INIT: {
td_mem_handle_t *fd = (td_mem_handle_t *)arg;
return drv_log_get_cfg_buf_fd(fd);
}
case LOG_CMPI_EXIT: {
td_mem_handle_t *fd = (td_mem_handle_t *)arg;
return drv_log_put_cfg_buf_fd(*fd);
}
#if defined(CONFIG_SOCT_LOG_NETWORK_SUPPORT) || defined(CONFIG_SOCT_LOG_UDISK_SUPPORT)
case LOG_CMPI_READ: {
return drv_log_network_or_udisk_read(cmd, arg);
}
case LOG_CMPI_WRITE: {
return drv_log_network_or_udisk_write(cmd, arg);
}
#endif
case LOG_CMPI_SET_SIZE: {
td_u32 *size = (td_u32 *)arg;
return ext_drv_log_set_size(*size);
}
case LOG_CMPI_STORE_ENABLE: {
drv_log_store_enable((td_bool *)arg);
return TD_SUCCESS;
}
case LOG_CMPI_GET_STORE_STATUS: {
log_store_status *param = (log_store_status *)arg;
drv_log_get_store_status(&(param->log_store_enable), &(param->log_store_thread_exist));
return TD_SUCCESS;
}
default:
soc_log_err("unknown command 0x%x\n", cmd);
return TD_FAILURE;
}
}
#ifdef CONFIG_COMPAT
td_s32 drv_log_compat_ioctl(unsigned int cmd, td_void *arg, td_void *private_data)
{
switch (cmd) {
#if defined(CONFIG_SOCT_LOG_NETWORK_SUPPORT) || defined(CONFIG_SOCT_LOG_UDISK_SUPPORT)
case LOG_CMPI_COMPAT_READ: {
log_compat_read_buf *para = (log_compat_read_buf *)arg;
if (para == TD_NULL || (td_u8 *)compat_ptr(para->msg_addr) == TD_NULL) {
soc_log_err("User buffer is null!\n");
return TD_FAILURE;
}
if (para->magic_num != LOG_MAGIC_NUM) {
soc_log_err("User buffer is likely illegal!\n");
return TD_FAILURE;
}
return ext_drv_log_read_buf((td_u8 *)compat_ptr(para->msg_addr), para->buf_len, &para->copy_len,
&para->task_status, TD_FALSE);
}
case LOG_CMPI_COMPAT_WRITE: {
log_compat_write_buf *para = (log_compat_write_buf *)arg;
if (para == TD_NULL || (td_u8 *)compat_ptr(para->msg_addr) == TD_NULL) {
soc_log_err("User buffer is null!\n");
return TD_FAILURE;
}
return ext_drv_log_write_buf((td_u8 *)compat_ptr(para->msg_addr), para->msg_len, LOG_MSG_FROM_USER);
}
#endif
default:
return drv_log_ioctl(cmd, arg, private_data);
}
return -ENOIOCTLCMD;
}
#endif