1092 lines
28 KiB
C
1092 lines
28 KiB
C
|
// SPDX-License-Identifier: GPL-2.0
|
||
|
/*
|
||
|
* Copyright (C) 2020 MediaTek Inc.
|
||
|
*/
|
||
|
|
||
|
#include <linux/fs.h> /* needed by file_operations* */
|
||
|
#include <linux/miscdevice.h> /* needed by miscdevice* */
|
||
|
#include <linux/device.h> /* needed by device_* */
|
||
|
#include <linux/uaccess.h> /* needed by copy_to_user */
|
||
|
#include <linux/fs.h> /* needed by file_operations* */
|
||
|
#include <linux/slab.h> /* needed by kmalloc */
|
||
|
#include <linux/poll.h> /* needed by poll */
|
||
|
#include <linux/vmalloc.h> /* needed by vmalloc */
|
||
|
#include <linux/mutex.h>
|
||
|
#include <linux/spinlock.h>
|
||
|
#include <linux/delay.h>
|
||
|
#include <linux/io.h>
|
||
|
//#include <mt-plat/sync_write.h>
|
||
|
#include "scp_helper.h"
|
||
|
#include "scp_ipi_pin.h"
|
||
|
#include "scp_mbox_layout.h"
|
||
|
#include "scp.h"
|
||
|
|
||
|
#define DRAM_BUF_LEN (1 * 1024 * 1024)
|
||
|
#define SCP_TIMER_TIMEOUT (1 * HZ) /* 1 seconds*/
|
||
|
#define ROUNDUP(a, b) (((a) + ((b)-1)) & ~((b)-1))
|
||
|
#define PLT_LOG_ENABLE 0x504C5402 /*magic*/
|
||
|
#define SCP_IPI_RETRY_TIMES (5000)
|
||
|
|
||
|
/* bit0 = 1, logger is on, else off*/
|
||
|
#define SCP_LOGGER_ON_BIT (1<<0)
|
||
|
/* bit1 = 1, logger_dram_use is on, else off*/
|
||
|
#define SCP_LOGGER_DRAM_ON_BIT (1<<1)
|
||
|
/* bit8 = 1, enable function (logger/logger dram use) */
|
||
|
#define SCP_LOGGER_ON_CTRL_BIT (1<<8)
|
||
|
/* bit8 = 0, disable function */
|
||
|
#define SCP_LOGGER_OFF_CTRL_BIT (0<<8)
|
||
|
/* let logger on */
|
||
|
#define SCP_LOGGER_ON (SCP_LOGGER_ON_CTRL_BIT | SCP_LOGGER_ON_BIT)
|
||
|
/* let logger off */
|
||
|
#define SCP_LOGGER_OFF (SCP_LOGGER_OFF_CTRL_BIT | SCP_LOGGER_ON_BIT)
|
||
|
/* let logger dram use on */
|
||
|
#define SCP_LOGGER_DRAM_ON (SCP_LOGGER_ON_CTRL_BIT | SCP_LOGGER_DRAM_ON_BIT)
|
||
|
/* let logger dram use off */
|
||
|
#define SCP_LOGGER_DRAM_OFF (SCP_LOGGER_OFF_CTRL_BIT | SCP_LOGGER_DRAM_ON_BIT)
|
||
|
#define SCP_LOGGER_UT (1)
|
||
|
|
||
|
struct log_ctrl_s {
|
||
|
unsigned int base;
|
||
|
unsigned int size;
|
||
|
unsigned int enable;
|
||
|
unsigned int info_ofs;
|
||
|
unsigned int buff_ofs;
|
||
|
unsigned int buff_size;
|
||
|
};
|
||
|
|
||
|
struct buffer_info_s {
|
||
|
unsigned int r_pos;
|
||
|
unsigned int w_pos;
|
||
|
};
|
||
|
|
||
|
struct SCP_LOG_INFO {
|
||
|
uint32_t scp_log_dram_addr;
|
||
|
uint32_t scp_log_buf_addr;
|
||
|
uint32_t scp_log_start_addr;
|
||
|
uint32_t scp_log_end_addr;
|
||
|
uint32_t scp_log_buf_maxlen;
|
||
|
};
|
||
|
|
||
|
struct scp_logger_ctrl_msg {
|
||
|
unsigned int cmd;
|
||
|
union {
|
||
|
struct {
|
||
|
unsigned int addr;
|
||
|
unsigned int size;
|
||
|
} init;
|
||
|
struct {
|
||
|
unsigned int enable;
|
||
|
} flag;
|
||
|
struct SCP_LOG_INFO info;
|
||
|
} u;
|
||
|
};
|
||
|
|
||
|
#define SCP_LOGGER_IPI_INIT 0x4C4F4701
|
||
|
#define SCP_LOGGER_IPI_ENABLE 0x4C4F4702
|
||
|
#define SCP_LOGGER_IPI_WAKEUP 0x4C4F4703
|
||
|
#define SCP_LOGGER_IPI_SET_FILTER 0x4C4F4704
|
||
|
|
||
|
static unsigned int scp_A_logger_inited;
|
||
|
static unsigned int scp_A_logger_wakeup_ap;
|
||
|
|
||
|
static struct log_ctrl_s *SCP_A_log_ctl;
|
||
|
static struct buffer_info_s *SCP_A_buf_info;
|
||
|
/*static struct timer_list scp_log_timer;*/
|
||
|
static DEFINE_MUTEX(scp_A_log_mutex);
|
||
|
static DEFINE_SPINLOCK(scp_A_log_buf_spinlock);
|
||
|
static struct scp_work_struct scp_logger_notify_work[SCP_CORE_TOTAL];
|
||
|
|
||
|
/*scp last log info*/
|
||
|
#define LAST_LOG_BUF_SIZE 4095
|
||
|
static struct SCP_LOG_INFO last_log_info;
|
||
|
|
||
|
static char *scp_A_last_log;
|
||
|
static wait_queue_head_t scp_A_logwait;
|
||
|
|
||
|
static DEFINE_MUTEX(scp_logger_mutex);
|
||
|
static char *scp_last_logger;
|
||
|
/*global value*/
|
||
|
unsigned int r_pos_debug;
|
||
|
unsigned int log_ctl_debug;
|
||
|
static struct mutex scp_logger_mutex;
|
||
|
|
||
|
/* ipi message buffer */
|
||
|
struct scp_logger_ctrl_msg msg_scp_logger_ctrl;
|
||
|
|
||
|
/*
|
||
|
* get log from scp when received a buf full notify
|
||
|
* @param id: IPI id
|
||
|
* @param prdata: IPI handler parameter
|
||
|
* @param data: IPI data
|
||
|
* @param len: IPI data length
|
||
|
*/
|
||
|
static int scp_logger_wakeup_handler(unsigned int id, void *prdata, void *data,
|
||
|
unsigned int len)
|
||
|
{
|
||
|
pr_debug("[SCP]wakeup by SCP logger\n");
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* get log from scp to last_log_buf
|
||
|
* @param len: data length
|
||
|
* @return: length of log
|
||
|
*/
|
||
|
static size_t scp_A_get_last_log(size_t b_len)
|
||
|
{
|
||
|
size_t ret = 0;
|
||
|
int scp_awake_flag;
|
||
|
unsigned int log_end_idx;
|
||
|
unsigned int update_start_idx;
|
||
|
unsigned char *scp_last_log_buf =
|
||
|
(unsigned char *)(SCP_TCM + last_log_info.scp_log_buf_addr);
|
||
|
|
||
|
/*pr_debug("[SCP] %s\n", __func__);*/
|
||
|
|
||
|
if (!scp_A_logger_inited) {
|
||
|
pr_notice("[SCP] %s(): logger has not been init\n", __func__);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
mutex_lock(&scp_logger_mutex);
|
||
|
|
||
|
/* SCP keep awake */
|
||
|
scp_awake_flag = 0;
|
||
|
if (scp_awake_lock((void *)SCP_A_ID) == -1) {
|
||
|
scp_awake_flag = -1;
|
||
|
pr_debug("[SCP] %s: awake scp fail\n", __func__);
|
||
|
}
|
||
|
/*cofirm last log information is less than tcm size*/
|
||
|
if (last_log_info.scp_log_end_addr > scpreg.total_tcmsize) {
|
||
|
pr_notice("[SCP] %s: last_log_info.scp_log_end_addr %x is over tcm_size %x\n",
|
||
|
__func__, last_log_info.scp_log_end_addr, scpreg.total_tcmsize);
|
||
|
goto exit;
|
||
|
}
|
||
|
if (last_log_info.scp_log_buf_addr + last_log_info.scp_log_buf_maxlen >
|
||
|
scpreg.total_tcmsize) {
|
||
|
pr_debug("[SCP] %s: end of last_log_info.scp_last_log_buf %x is over tcm_size %x\n",
|
||
|
__func__, last_log_info.scp_log_buf_addr + last_log_info.scp_log_buf_maxlen,
|
||
|
scpreg.total_tcmsize);
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
log_end_idx = readl((void __iomem *)(SCP_TCM +
|
||
|
last_log_info.scp_log_end_addr));
|
||
|
|
||
|
if (b_len > last_log_info.scp_log_buf_maxlen) {
|
||
|
pr_debug("[SCP] b_len %zu > scp_log_buf_maxlen %d\n",
|
||
|
b_len, last_log_info.scp_log_buf_maxlen);
|
||
|
b_len = last_log_info.scp_log_buf_maxlen;
|
||
|
}
|
||
|
/* handle sram error */
|
||
|
if (log_end_idx >= last_log_info.scp_log_buf_maxlen)
|
||
|
log_end_idx = 0;
|
||
|
|
||
|
if (log_end_idx >= b_len)
|
||
|
update_start_idx = log_end_idx - b_len;
|
||
|
else
|
||
|
update_start_idx = last_log_info.scp_log_buf_maxlen -
|
||
|
(b_len - log_end_idx) + 1;
|
||
|
|
||
|
/* read log from scp buffer */
|
||
|
ret = 0;
|
||
|
if (scp_A_last_log) {
|
||
|
while ((update_start_idx != log_end_idx) && ret < b_len) {
|
||
|
scp_A_last_log[ret] =
|
||
|
scp_last_log_buf[update_start_idx];
|
||
|
update_start_idx++;
|
||
|
ret++;
|
||
|
if (update_start_idx >=
|
||
|
last_log_info.scp_log_buf_maxlen)
|
||
|
update_start_idx = update_start_idx -
|
||
|
last_log_info.scp_log_buf_maxlen;
|
||
|
|
||
|
scp_A_last_log[ret] = '\0';
|
||
|
}
|
||
|
} else {
|
||
|
/* no buffer, just skip logs*/
|
||
|
update_start_idx = log_end_idx;
|
||
|
}
|
||
|
exit:
|
||
|
/*SCP release awake */
|
||
|
if (scp_awake_flag == 0) {
|
||
|
if (scp_awake_unlock((void *)SCP_A_ID) == -1)
|
||
|
pr_debug("[SCP] %s: awake unlock fail\n", __func__);
|
||
|
}
|
||
|
|
||
|
mutex_unlock(&scp_logger_mutex);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
ssize_t scp_A_log_read(char __user *data, size_t len)
|
||
|
{
|
||
|
unsigned int w_pos, r_pos, datalen;
|
||
|
char *buf;
|
||
|
|
||
|
if (!scp_A_logger_inited)
|
||
|
return 0;
|
||
|
|
||
|
datalen = 0;
|
||
|
|
||
|
mutex_lock(&scp_A_log_mutex);
|
||
|
|
||
|
r_pos = SCP_A_buf_info->r_pos;
|
||
|
w_pos = SCP_A_buf_info->w_pos;
|
||
|
|
||
|
if (r_pos == w_pos)
|
||
|
goto error;
|
||
|
|
||
|
if (r_pos > w_pos)
|
||
|
datalen = DRAM_BUF_LEN - r_pos; /* not wrap */
|
||
|
else
|
||
|
datalen = w_pos - r_pos;
|
||
|
|
||
|
if (datalen > len)
|
||
|
datalen = len;
|
||
|
|
||
|
/*debug for logger pos fail*/
|
||
|
r_pos_debug = r_pos;
|
||
|
log_ctl_debug = SCP_A_log_ctl->buff_ofs;
|
||
|
if (r_pos >= DRAM_BUF_LEN) {
|
||
|
pr_notice("[SCP] %s(): r_pos >= DRAM_BUF_LEN,%x,%x\n",
|
||
|
__func__, r_pos_debug, log_ctl_debug);
|
||
|
datalen = 0;
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
buf = ((char *) SCP_A_log_ctl) + SCP_A_log_ctl->buff_ofs + r_pos;
|
||
|
|
||
|
len = datalen;
|
||
|
/*memory copy from log buf*/
|
||
|
if (copy_to_user(data, buf, len))
|
||
|
pr_debug("[SCP]copy to user buf failed..\n");
|
||
|
|
||
|
r_pos += datalen;
|
||
|
if (r_pos >= DRAM_BUF_LEN)
|
||
|
r_pos -= DRAM_BUF_LEN;
|
||
|
|
||
|
SCP_A_buf_info->r_pos = r_pos;
|
||
|
|
||
|
error:
|
||
|
mutex_unlock(&scp_A_log_mutex);
|
||
|
|
||
|
return datalen;
|
||
|
}
|
||
|
|
||
|
unsigned int scp_A_log_poll(void)
|
||
|
{
|
||
|
if (!scp_A_logger_inited)
|
||
|
return 0;
|
||
|
|
||
|
if (SCP_A_buf_info->r_pos != SCP_A_buf_info->w_pos)
|
||
|
return POLLIN | POLLRDNORM;
|
||
|
|
||
|
/*scp_log_timer_add();*/
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
static ssize_t scp_A_log_if_read(struct file *file,
|
||
|
char __user *data, size_t len, loff_t *ppos)
|
||
|
{
|
||
|
ssize_t ret;
|
||
|
|
||
|
/*pr_debug("[SCP A] scp_A_log_if_read\n");*/
|
||
|
|
||
|
ret = 0;
|
||
|
|
||
|
/*if (access_ok(VERIFY_WRITE, data, len))*/
|
||
|
ret = scp_A_log_read(data, len);
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
static int scp_A_log_if_open(struct inode *inode, struct file *file)
|
||
|
{
|
||
|
/*pr_debug("[SCP A] scp_A_log_if_open\n");*/
|
||
|
return nonseekable_open(inode, file);
|
||
|
}
|
||
|
|
||
|
static unsigned int scp_A_log_if_poll(struct file *file, poll_table *wait)
|
||
|
{
|
||
|
unsigned int ret = 0;
|
||
|
|
||
|
/* pr_debug("[SCP A] scp_A_log_if_poll\n"); */
|
||
|
if (!scp_A_logger_inited)
|
||
|
return 0;
|
||
|
|
||
|
if (!(file->f_mode & FMODE_READ))
|
||
|
return ret;
|
||
|
|
||
|
/*poll_wait(file, &scp_A_logwait, wait);*/
|
||
|
|
||
|
ret = scp_A_log_poll();
|
||
|
|
||
|
return ret;
|
||
|
}
|
||
|
/*
|
||
|
* ipi send to enable scp logger flag
|
||
|
*/
|
||
|
static unsigned int scp_A_log_enable_set(unsigned int enable)
|
||
|
{
|
||
|
int ret;
|
||
|
unsigned int retrytimes;
|
||
|
struct scp_logger_ctrl_msg msg;
|
||
|
|
||
|
if (scp_A_logger_inited) {
|
||
|
/*
|
||
|
*send ipi to invoke scp logger
|
||
|
*/
|
||
|
ret = 0;
|
||
|
enable = (enable) ? SCP_LOGGER_ON : SCP_LOGGER_OFF;
|
||
|
retrytimes = SCP_IPI_RETRY_TIMES;
|
||
|
do {
|
||
|
msg.cmd = SCP_LOGGER_IPI_ENABLE;
|
||
|
msg.u.flag.enable = enable;
|
||
|
ret = mtk_ipi_send(&scp_ipidev, IPI_OUT_LOGGER_CTRL,
|
||
|
0, &msg, sizeof(msg)/MBOX_SLOT_SIZE, 0);
|
||
|
|
||
|
if (ret == IPI_ACTION_DONE)
|
||
|
break;
|
||
|
retrytimes--;
|
||
|
udelay(100);
|
||
|
} while (retrytimes > 0);
|
||
|
/*
|
||
|
*disable/enable logger flag
|
||
|
*/
|
||
|
if ((ret == IPI_ACTION_DONE) && (enable == SCP_LOGGER_ON))
|
||
|
SCP_A_log_ctl->enable = 1;
|
||
|
else if ((ret == IPI_ACTION_DONE) && (enable == SCP_LOGGER_OFF))
|
||
|
SCP_A_log_ctl->enable = 0;
|
||
|
|
||
|
if (ret != IPI_ACTION_DONE) {
|
||
|
pr_notice("[SCP] %s: fail ret=%d\n", __func__, ret);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
*ipi send enable scp logger wake up flag
|
||
|
*/
|
||
|
static unsigned int scp_A_log_wakeup_set(unsigned int enable)
|
||
|
{
|
||
|
int ret;
|
||
|
unsigned int retrytimes;
|
||
|
struct scp_logger_ctrl_msg msg;
|
||
|
|
||
|
if (scp_A_logger_inited) {
|
||
|
/*
|
||
|
*send ipi to invoke scp logger
|
||
|
*/
|
||
|
ret = 0;
|
||
|
enable = (enable) ? 1 : 0;
|
||
|
retrytimes = SCP_IPI_RETRY_TIMES;
|
||
|
do {
|
||
|
msg.cmd = SCP_LOGGER_IPI_WAKEUP;
|
||
|
msg.u.flag.enable = enable;
|
||
|
ret = mtk_ipi_send(&scp_ipidev, IPI_OUT_LOGGER_CTRL,
|
||
|
0, &msg, sizeof(msg)/MBOX_SLOT_SIZE, 0);
|
||
|
|
||
|
if (ret == IPI_ACTION_DONE)
|
||
|
break;
|
||
|
retrytimes--;
|
||
|
udelay(100);
|
||
|
} while (retrytimes > 0);
|
||
|
/*
|
||
|
*disable/enable logger flag
|
||
|
*/
|
||
|
if ((ret == IPI_ACTION_DONE) && (enable == 1))
|
||
|
scp_A_logger_wakeup_ap = 1;
|
||
|
else if ((ret == IPI_ACTION_DONE) && (enable == 0))
|
||
|
scp_A_logger_wakeup_ap = 0;
|
||
|
|
||
|
if (ret != IPI_ACTION_DONE) {
|
||
|
pr_notice("[SCP] %s: fail ret=%d\n", __func__, ret);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
error:
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* create device sysfs, scp logger status
|
||
|
*/
|
||
|
static ssize_t scp_mobile_log_show(struct device *kobj,
|
||
|
struct device_attribute *attr, char *buf)
|
||
|
{
|
||
|
unsigned int stat;
|
||
|
|
||
|
stat = (scp_A_logger_inited && SCP_A_log_ctl->enable) ? 1 : 0;
|
||
|
|
||
|
return sprintf(buf, "[SCP A] mobile log is %s\n",
|
||
|
(stat == 0x1) ? "enabled" : "disabled");
|
||
|
}
|
||
|
|
||
|
static ssize_t scp_mobile_log_store(struct device *kobj,
|
||
|
struct device_attribute *attr, const char *buf, size_t n)
|
||
|
{
|
||
|
unsigned int enable;
|
||
|
|
||
|
if (kstrtouint(buf, 0, &enable) != 0)
|
||
|
return -EINVAL;
|
||
|
|
||
|
mutex_lock(&scp_A_log_mutex);
|
||
|
scp_A_log_enable_set(enable);
|
||
|
mutex_unlock(&scp_A_log_mutex);
|
||
|
|
||
|
return n;
|
||
|
}
|
||
|
DEVICE_ATTR_RW(scp_mobile_log);
|
||
|
|
||
|
|
||
|
/*
|
||
|
* create device sysfs, scp ADB cmd to set SCP wakeup AP flag
|
||
|
*/
|
||
|
static ssize_t scp_A_logger_wakeup_AP_show(struct device *kobj,
|
||
|
struct device_attribute *attr, char *buf)
|
||
|
{
|
||
|
unsigned int stat;
|
||
|
|
||
|
stat = (scp_A_logger_inited && scp_A_logger_wakeup_ap) ? 1 : 0;
|
||
|
|
||
|
return sprintf(buf, "[SCP A] logger wakeup AP is %s\n",
|
||
|
(stat == 0x1) ? "enabled" : "disabled");
|
||
|
}
|
||
|
|
||
|
static ssize_t scp_A_logger_wakeup_AP_store(struct device *kobj,
|
||
|
struct device_attribute *attr, const char *buf, size_t n)
|
||
|
{
|
||
|
unsigned int enable;
|
||
|
|
||
|
if (kstrtouint(buf, 0, &enable) != 0)
|
||
|
return -EINVAL;
|
||
|
|
||
|
mutex_lock(&scp_A_log_mutex);
|
||
|
scp_A_log_wakeup_set(enable);
|
||
|
mutex_unlock(&scp_A_log_mutex);
|
||
|
|
||
|
return n;
|
||
|
}
|
||
|
|
||
|
DEVICE_ATTR_RW(scp_A_logger_wakeup_AP);
|
||
|
|
||
|
/*
|
||
|
* create device sysfs, scp last log show
|
||
|
*/
|
||
|
static ssize_t scp_A_get_last_log_show(struct device *kobj,
|
||
|
struct device_attribute *attr, char *buf)
|
||
|
{
|
||
|
scp_A_get_last_log(last_log_info.scp_log_buf_maxlen);
|
||
|
return sprintf(buf, "scp_log_buf_maxlen=%u, log=%s\n",
|
||
|
last_log_info.scp_log_buf_maxlen,
|
||
|
scp_A_last_log ? scp_A_last_log : "");
|
||
|
}
|
||
|
|
||
|
DEVICE_ATTR_RO(scp_A_get_last_log);
|
||
|
|
||
|
/*
|
||
|
* logger UT test
|
||
|
*
|
||
|
*/
|
||
|
#if SCP_LOGGER_UT
|
||
|
static ssize_t scp_A_mobile_log_UT_show(struct device *kobj,
|
||
|
struct device_attribute *attr, char *buf)
|
||
|
{
|
||
|
unsigned int w_pos, r_pos, datalen;
|
||
|
char *logger_buf;
|
||
|
size_t len = 1024;
|
||
|
|
||
|
if (!scp_A_logger_inited)
|
||
|
return 0;
|
||
|
|
||
|
datalen = 0;
|
||
|
|
||
|
mutex_lock(&scp_A_log_mutex);
|
||
|
|
||
|
r_pos = SCP_A_buf_info->r_pos;
|
||
|
w_pos = SCP_A_buf_info->w_pos;
|
||
|
|
||
|
if (r_pos == w_pos)
|
||
|
goto error;
|
||
|
|
||
|
if (r_pos > w_pos)
|
||
|
datalen = DRAM_BUF_LEN - r_pos; /* not wrap */
|
||
|
else
|
||
|
datalen = w_pos - r_pos;
|
||
|
|
||
|
if (datalen > len)
|
||
|
datalen = len;
|
||
|
|
||
|
logger_buf = ((char *) SCP_A_log_ctl) +
|
||
|
SCP_A_log_ctl->buff_ofs + r_pos;
|
||
|
|
||
|
len = datalen;
|
||
|
/*memory copy from log buf*/
|
||
|
memcpy_fromio(buf, logger_buf, len);
|
||
|
|
||
|
r_pos += datalen;
|
||
|
if (r_pos >= DRAM_BUF_LEN)
|
||
|
r_pos -= DRAM_BUF_LEN;
|
||
|
|
||
|
SCP_A_buf_info->r_pos = r_pos;
|
||
|
|
||
|
error:
|
||
|
mutex_unlock(&scp_A_log_mutex);
|
||
|
|
||
|
return len;
|
||
|
}
|
||
|
|
||
|
static ssize_t scp_A_mobile_log_UT_store(struct device *kobj,
|
||
|
struct device_attribute *attr, const char *buf, size_t n)
|
||
|
{
|
||
|
unsigned int enable;
|
||
|
|
||
|
if (kstrtouint(buf, 0, &enable) != 0)
|
||
|
return -EINVAL;
|
||
|
|
||
|
mutex_lock(&scp_A_log_mutex);
|
||
|
scp_A_log_enable_set(enable);
|
||
|
mutex_unlock(&scp_A_log_mutex);
|
||
|
|
||
|
return n;
|
||
|
}
|
||
|
|
||
|
DEVICE_ATTR_RW(scp_A_mobile_log_UT);
|
||
|
#endif
|
||
|
|
||
|
static ssize_t log_filter_store(struct device *dev,
|
||
|
struct device_attribute *attr, const char *buf, size_t count)
|
||
|
{
|
||
|
int ret;
|
||
|
uint32_t filter;
|
||
|
struct scp_logger_ctrl_msg msg;
|
||
|
|
||
|
if (sscanf(buf, "0x%08x", &filter) != 1)
|
||
|
return -EINVAL;
|
||
|
|
||
|
msg.cmd = SCP_LOGGER_IPI_SET_FILTER;
|
||
|
msg.u.flag.enable = filter;
|
||
|
ret = mtk_ipi_send(&scp_ipidev, IPI_OUT_LOGGER_CTRL, 0, &msg,
|
||
|
sizeof(msg)/MBOX_SLOT_SIZE, 0);
|
||
|
switch (ret) {
|
||
|
case IPI_ACTION_DONE:
|
||
|
pr_notice("[SCP] Set log filter to 0x%08x\n", filter);
|
||
|
return count;
|
||
|
|
||
|
case IPI_PIN_BUSY:
|
||
|
pr_notice("[SCP] IPI busy. Set log filter failed!\n");
|
||
|
return -EBUSY;
|
||
|
|
||
|
default:
|
||
|
pr_notice("[SCP] IPI error. Set log filter failed!\n");
|
||
|
return -EIO;
|
||
|
}
|
||
|
}
|
||
|
DEVICE_ATTR_WO(log_filter);
|
||
|
|
||
|
|
||
|
/*
|
||
|
* IPI for logger init
|
||
|
*/
|
||
|
static int scp_logger_init_handler(struct SCP_LOG_INFO *log_info)
|
||
|
{
|
||
|
unsigned long flags;
|
||
|
|
||
|
pr_debug("[SCP]scp_get_reserve_mem_phys=%llx\n",
|
||
|
(uint64_t)scp_get_reserve_mem_phys(SCP_A_LOGGER_MEM_ID));
|
||
|
spin_lock_irqsave(&scp_A_log_buf_spinlock, flags);
|
||
|
/* sync scp last log information*/
|
||
|
last_log_info.scp_log_dram_addr = log_info->scp_log_dram_addr;
|
||
|
last_log_info.scp_log_buf_addr = log_info->scp_log_buf_addr;
|
||
|
last_log_info.scp_log_start_addr = log_info->scp_log_start_addr;
|
||
|
last_log_info.scp_log_end_addr = log_info->scp_log_end_addr;
|
||
|
last_log_info.scp_log_buf_maxlen = log_info->scp_log_buf_maxlen;
|
||
|
/*cofirm last log information is less than tcm size*/
|
||
|
if (last_log_info.scp_log_dram_addr > scpreg.total_tcmsize)
|
||
|
pr_notice("[SCP]last_log_info.scp_log_dram_addr %x is over tcm_size %x\n",
|
||
|
last_log_info.scp_log_dram_addr, scpreg.total_tcmsize);
|
||
|
if (last_log_info.scp_log_buf_addr > scpreg.total_tcmsize)
|
||
|
pr_notice("[SCP]last_log_info.scp_log_buf_addr %x is over tcm_size %x\n",
|
||
|
last_log_info.scp_log_buf_addr, scpreg.total_tcmsize);
|
||
|
if (last_log_info.scp_log_start_addr > scpreg.total_tcmsize)
|
||
|
pr_notice("[SCP]last_log_info.scp_log_start_addr %x is over tcm_size %x\n",
|
||
|
last_log_info.scp_log_start_addr, scpreg.total_tcmsize);
|
||
|
if (last_log_info.scp_log_end_addr > scpreg.total_tcmsize)
|
||
|
pr_notice("[SCP]last_log_info.scp_log_end_addr %x is over tcm_size %x\n",
|
||
|
last_log_info.scp_log_end_addr, scpreg.total_tcmsize);
|
||
|
if (last_log_info.scp_log_buf_addr + last_log_info.scp_log_buf_maxlen >
|
||
|
scpreg.total_tcmsize)
|
||
|
pr_notice("[SCP] end of last_log_info.scp_last_log_buf %x is over tcm_size %x\n",
|
||
|
last_log_info.scp_log_buf_addr + last_log_info.scp_log_buf_maxlen,
|
||
|
scpreg.total_tcmsize);
|
||
|
|
||
|
/* setting dram ctrl config to scp*/
|
||
|
/* scp side get wakelock, AP to write info to scp sram*/
|
||
|
mt_reg_sync_writel(scp_get_reserve_mem_phys(SCP_A_LOGGER_MEM_ID),
|
||
|
(SCP_TCM + last_log_info.scp_log_dram_addr));
|
||
|
/* set init flag here*/
|
||
|
scp_A_logger_inited = 1;
|
||
|
spin_unlock_irqrestore(&scp_A_log_buf_spinlock, flags);
|
||
|
|
||
|
/*set a wq to enable scp logger*/
|
||
|
scp_logger_notify_work[SCP_A_ID].id = SCP_A_ID;
|
||
|
#if SCP_LOGGER_ENABLE
|
||
|
scp_schedule_logger_work(&scp_logger_notify_work[SCP_A_ID]);
|
||
|
#endif
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* IPI for logger control
|
||
|
* @param id: IPI id
|
||
|
* @param prdata: callback function parameter
|
||
|
* @param data: IPI data
|
||
|
* @param len: IPI data length
|
||
|
*/
|
||
|
static int scp_logger_ctrl_handler(unsigned int id, void *prdata, void *data,
|
||
|
unsigned int len)
|
||
|
{
|
||
|
struct scp_logger_ctrl_msg msg = *(struct scp_logger_ctrl_msg *)data;
|
||
|
|
||
|
switch (msg.cmd) {
|
||
|
case SCP_LOGGER_IPI_INIT:
|
||
|
scp_logger_init_handler(&msg.u.info);
|
||
|
break;
|
||
|
case SCP_LOGGER_IPI_WAKEUP:
|
||
|
scp_logger_wakeup_handler(id, prdata, &msg.u.flag, len);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* callback function for work struct
|
||
|
* notify apps to start their tasks or generate an exception according to flag
|
||
|
* NOTE: this function may be blocked and should not be called in interrupt
|
||
|
* context
|
||
|
* @param ws: work struct
|
||
|
*/
|
||
|
static void scp_logger_notify_ws(struct work_struct *ws)
|
||
|
{
|
||
|
unsigned int retrytimes;
|
||
|
int ret;
|
||
|
unsigned int scp_ipi_id;
|
||
|
struct scp_logger_ctrl_msg msg;
|
||
|
|
||
|
scp_ipi_id = IPI_OUT_LOGGER_CTRL;
|
||
|
msg.cmd = SCP_LOGGER_IPI_INIT;
|
||
|
msg.u.init.addr = scp_get_reserve_mem_phys(SCP_A_LOGGER_MEM_ID);
|
||
|
msg.u.init.size = scp_get_reserve_mem_size(SCP_A_LOGGER_MEM_ID);
|
||
|
|
||
|
pr_notice("[SCP] %s: id=%u\n", __func__, scp_ipi_id);
|
||
|
/*
|
||
|
*send ipi to invoke scp logger
|
||
|
*/
|
||
|
retrytimes = SCP_IPI_RETRY_TIMES;
|
||
|
do {
|
||
|
ret = mtk_ipi_send(&scp_ipidev, scp_ipi_id, 0, &msg,
|
||
|
sizeof(msg)/MBOX_SLOT_SIZE, 0);
|
||
|
|
||
|
if ((retrytimes % 500) == 0)
|
||
|
pr_debug("[SCP] %s: ipi ret=%d\n", __func__, ret);
|
||
|
if (ret == IPI_ACTION_DONE)
|
||
|
break;
|
||
|
retrytimes--;
|
||
|
udelay(2000);
|
||
|
} while (retrytimes > 0);
|
||
|
|
||
|
/*enable logger flag*/
|
||
|
if (ret == IPI_ACTION_DONE)
|
||
|
SCP_A_log_ctl->enable = 1;
|
||
|
else {
|
||
|
/*scp logger ipi init fail but still let logger dump*/
|
||
|
SCP_A_log_ctl->enable = 1;
|
||
|
pr_notice("[SCP]logger initial fail, ipi ret=%d\n", ret);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
static int scp_logger_notify_callback(struct notifier_block *this,
|
||
|
unsigned long event, void *ptr)
|
||
|
{
|
||
|
switch (event) {
|
||
|
case SCP_EVENT_READY:
|
||
|
#if SCP_LOGGER_ENABLE
|
||
|
scp_schedule_logger_work(&scp_logger_notify_work[SCP_A_ID]);
|
||
|
#endif
|
||
|
break;
|
||
|
}
|
||
|
return NOTIFY_DONE;
|
||
|
}
|
||
|
static struct notifier_block scp_logger_notify = {
|
||
|
.notifier_call = scp_logger_notify_callback,
|
||
|
};
|
||
|
|
||
|
/******************************************************************************
|
||
|
* init scp logger dram ctrl structure
|
||
|
* @return: -1: fail, otherwise: end of buffer
|
||
|
*****************************************************************************/
|
||
|
int scp_logger_init(phys_addr_t start, phys_addr_t limit)
|
||
|
{
|
||
|
int last_ofs;
|
||
|
|
||
|
/*init wait queue*/
|
||
|
init_waitqueue_head(&scp_A_logwait);
|
||
|
scp_A_logger_wakeup_ap = 0;
|
||
|
mutex_init(&scp_logger_mutex);
|
||
|
/*init work queue*/
|
||
|
INIT_WORK(&scp_logger_notify_work[SCP_A_ID].work, scp_logger_notify_ws);
|
||
|
|
||
|
/*init dram ctrl table*/
|
||
|
last_ofs = 0;
|
||
|
#ifdef CONFIG_ARM64
|
||
|
SCP_A_log_ctl = (struct log_ctrl_s *) start;
|
||
|
#else
|
||
|
/* plz fix origial ptr to phys_addr flow */
|
||
|
SCP_A_log_ctl = (struct log_ctrl_s *) (u32) start;
|
||
|
#endif
|
||
|
SCP_A_log_ctl->base = PLT_LOG_ENABLE; /* magic */
|
||
|
SCP_A_log_ctl->enable = 0;
|
||
|
SCP_A_log_ctl->size = sizeof(*SCP_A_log_ctl);
|
||
|
|
||
|
last_ofs += SCP_A_log_ctl->size;
|
||
|
SCP_A_log_ctl->info_ofs = last_ofs;
|
||
|
|
||
|
last_ofs += sizeof(*SCP_A_buf_info);
|
||
|
last_ofs = ROUNDUP(last_ofs, 4);
|
||
|
SCP_A_log_ctl->buff_ofs = last_ofs;
|
||
|
SCP_A_log_ctl->buff_size = DRAM_BUF_LEN;
|
||
|
|
||
|
SCP_A_buf_info = (struct buffer_info_s *)
|
||
|
(((unsigned char *) SCP_A_log_ctl) + SCP_A_log_ctl->info_ofs);
|
||
|
SCP_A_buf_info->r_pos = 0;
|
||
|
SCP_A_buf_info->w_pos = 0;
|
||
|
|
||
|
last_ofs += SCP_A_log_ctl->buff_size;
|
||
|
|
||
|
if (last_ofs >= limit) {
|
||
|
pr_notice("[SCP]:%s() initial fail, last_ofs=%u, limit=%u\n",
|
||
|
__func__, last_ofs, (unsigned int) limit);
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
/* init last log buffer*/
|
||
|
last_log_info.scp_log_buf_maxlen = LAST_LOG_BUF_SIZE;
|
||
|
if (!scp_A_last_log) {
|
||
|
/* Allocate one more byte for the NULL character. */
|
||
|
scp_A_last_log = vmalloc(last_log_info.scp_log_buf_maxlen + 1);
|
||
|
}
|
||
|
|
||
|
/* register logger ctrl IPI */
|
||
|
mtk_ipi_register(&scp_ipidev, IPI_IN_LOGGER_CTRL,
|
||
|
(void *)scp_logger_ctrl_handler, NULL,
|
||
|
&msg_scp_logger_ctrl);
|
||
|
|
||
|
scp_A_register_notify(&scp_logger_notify);
|
||
|
scp_A_logger_inited = 1;
|
||
|
|
||
|
return last_ofs;
|
||
|
|
||
|
error:
|
||
|
scp_A_logger_inited = 0;
|
||
|
SCP_A_log_ctl = NULL;
|
||
|
SCP_A_buf_info = NULL;
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
void scp_logger_uninit(void)
|
||
|
{
|
||
|
char *tmp = scp_A_last_log;
|
||
|
|
||
|
scp_A_logger_inited = 0;
|
||
|
scp_A_last_log = NULL;
|
||
|
if (tmp)
|
||
|
vfree(tmp);
|
||
|
}
|
||
|
|
||
|
const struct file_operations scp_A_log_file_ops = {
|
||
|
.owner = THIS_MODULE,
|
||
|
.read = scp_A_log_if_read,
|
||
|
.open = scp_A_log_if_open,
|
||
|
.poll = scp_A_log_if_poll,
|
||
|
};
|
||
|
|
||
|
|
||
|
/*
|
||
|
* move scp last log from sram to dram
|
||
|
* NOTE: this function may be blocked
|
||
|
* @param scp_core_id: fill scp id to get last log
|
||
|
*/
|
||
|
void scp_crash_log_move_to_buf(enum scp_core_id scp_id)
|
||
|
{
|
||
|
int pos;
|
||
|
unsigned int ret;
|
||
|
unsigned int length;
|
||
|
unsigned int log_buf_idx; /* SCP log buf pointer */
|
||
|
unsigned int log_start_idx; /* SCP log start pointer */
|
||
|
unsigned int log_end_idx; /* SCP log end pointer */
|
||
|
unsigned int w_pos; /* buf write pointer */
|
||
|
char *dram_logger_limit = /* SCP log reserve limitation */
|
||
|
(char *)(scp_get_reserve_mem_virt(SCP_A_LOGGER_MEM_ID)
|
||
|
+ scp_get_reserve_mem_size(SCP_A_LOGGER_MEM_ID));
|
||
|
char *pre_scp_logger_buf = NULL;
|
||
|
char *dram_logger_buf; /* dram buffer */
|
||
|
int scp_awake_flag;
|
||
|
|
||
|
char *crash_message = "****SCP EE LOG DUMP****\n";
|
||
|
unsigned char *scp_logger_buf = (unsigned char *)(SCP_TCM +
|
||
|
last_log_info.scp_log_buf_addr);
|
||
|
|
||
|
if (!scp_A_logger_inited && scp_id == SCP_A_ID) {
|
||
|
pr_notice("[SCP] %s(): logger has not been init\n", __func__);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
mutex_lock(&scp_logger_mutex);
|
||
|
|
||
|
/* SCP keep awake */
|
||
|
scp_awake_flag = 0;
|
||
|
if (scp_awake_lock((void *)scp_id) == -1) {
|
||
|
scp_awake_flag = -1;
|
||
|
pr_debug("[SCP] %s: awake scp fail\n", __func__);
|
||
|
}
|
||
|
|
||
|
/*cofirm last log information is less than tcm size*/
|
||
|
if (last_log_info.scp_log_buf_addr > scpreg.total_tcmsize) {
|
||
|
pr_notice("[SCP] %s: last_log_info.scp_log_buf_addr %x is over tcm_size %x\n",
|
||
|
__func__, last_log_info.scp_log_buf_addr, scpreg.total_tcmsize);
|
||
|
goto exit;
|
||
|
}
|
||
|
if (last_log_info.scp_log_start_addr > scpreg.total_tcmsize) {
|
||
|
pr_notice("[SCP] %s: last_log_info.scp_log_start_addr %x is over tcm_size %x\n",
|
||
|
__func__, last_log_info.scp_log_start_addr, scpreg.total_tcmsize);
|
||
|
goto exit;
|
||
|
}
|
||
|
if (last_log_info.scp_log_end_addr > scpreg.total_tcmsize) {
|
||
|
pr_notice("[SCP] %s: last_log_info.scp_log_end_addr %x is over tcm_size %x\n",
|
||
|
__func__, last_log_info.scp_log_end_addr, scpreg.total_tcmsize);
|
||
|
goto exit;
|
||
|
}
|
||
|
if (last_log_info.scp_log_buf_addr + last_log_info.scp_log_buf_maxlen >
|
||
|
scpreg.total_tcmsize) {
|
||
|
pr_debug("[SCP] %s: end of last_log_info.scp_last_log_buf %x is over tcm_size %x\n",
|
||
|
__func__, last_log_info.scp_log_buf_addr + last_log_info.scp_log_buf_maxlen,
|
||
|
scpreg.total_tcmsize);
|
||
|
goto exit;
|
||
|
}
|
||
|
log_buf_idx = readl((void __iomem *)(SCP_TCM +
|
||
|
last_log_info.scp_log_buf_addr));
|
||
|
log_start_idx = readl((void __iomem *)(SCP_TCM +
|
||
|
last_log_info.scp_log_start_addr));
|
||
|
log_end_idx = readl((void __iomem *)(SCP_TCM +
|
||
|
last_log_info.scp_log_end_addr));
|
||
|
|
||
|
/* if loggger_r/w_pos was messed up, dump all message in logger_buf */
|
||
|
if (((log_start_idx < log_buf_idx + last_log_info.scp_log_buf_maxlen)
|
||
|
|| (log_start_idx >= log_buf_idx))
|
||
|
&& ((log_end_idx < log_buf_idx + last_log_info.scp_log_buf_maxlen)
|
||
|
|| (log_end_idx >= log_buf_idx))) {
|
||
|
|
||
|
if (log_end_idx >= log_start_idx)
|
||
|
length = log_end_idx - log_start_idx;
|
||
|
else
|
||
|
length = last_log_info.scp_log_buf_maxlen -
|
||
|
(log_start_idx - log_end_idx);
|
||
|
} else {
|
||
|
length = last_log_info.scp_log_buf_maxlen;
|
||
|
log_start_idx = log_buf_idx;
|
||
|
log_end_idx = log_buf_idx + length - 1;
|
||
|
}
|
||
|
|
||
|
if (length >= last_log_info.scp_log_buf_maxlen) {
|
||
|
pr_notice("[SCP] %s: length >= max\n", __func__);
|
||
|
length = last_log_info.scp_log_buf_maxlen;
|
||
|
}
|
||
|
|
||
|
pre_scp_logger_buf = scp_last_logger;
|
||
|
scp_last_logger = vmalloc(length + strlen(crash_message) + 1);
|
||
|
if (log_start_idx > last_log_info.scp_log_buf_maxlen) {
|
||
|
pr_debug("[SCP] %s: scp_logger_buf +log_start_idx %x is over tcm_size %x\n",
|
||
|
__func__, last_log_info.scp_log_buf_addr + log_start_idx,
|
||
|
scpreg.total_tcmsize);
|
||
|
goto exit;
|
||
|
}
|
||
|
/* read log from scp buffer */
|
||
|
ret = 0;
|
||
|
if (scp_last_logger) {
|
||
|
ret += snprintf(scp_last_logger, strlen(crash_message),
|
||
|
crash_message);
|
||
|
ret--;
|
||
|
while ((log_start_idx != log_end_idx) &&
|
||
|
ret <= (length + strlen(crash_message))) {
|
||
|
scp_last_logger[ret] = scp_logger_buf[log_start_idx];
|
||
|
log_start_idx++;
|
||
|
ret++;
|
||
|
if (log_start_idx >= last_log_info.scp_log_buf_maxlen)
|
||
|
log_start_idx = log_start_idx -
|
||
|
last_log_info.scp_log_buf_maxlen;
|
||
|
|
||
|
scp_last_logger[ret] = '\0';
|
||
|
}
|
||
|
} else {
|
||
|
/* no buffer, just skip logs */
|
||
|
log_start_idx = log_end_idx;
|
||
|
}
|
||
|
|
||
|
if (ret != 0) {
|
||
|
/* get buffer w pos */
|
||
|
w_pos = SCP_A_buf_info->w_pos;
|
||
|
|
||
|
if (w_pos >= DRAM_BUF_LEN) {
|
||
|
pr_notice("[SCP] %s(): w_pos >= DRAM_BUF_LEN, w_pos=%u",
|
||
|
__func__, w_pos);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* copy to dram buffer */
|
||
|
dram_logger_buf = ((char *) SCP_A_log_ctl) +
|
||
|
SCP_A_log_ctl->buff_ofs + w_pos;
|
||
|
/* check write address don't over logger reserve memory */
|
||
|
if (dram_logger_buf > dram_logger_limit) {
|
||
|
pr_debug("[SCP] %s: dram_logger_buf %x oversize reserve mem %x\n",
|
||
|
__func__, dram_logger_buf, dram_logger_limit);
|
||
|
goto exit;
|
||
|
}
|
||
|
|
||
|
/* memory copy from log buf */
|
||
|
pos = 0;
|
||
|
while ((pos != ret) && pos <= ret) {
|
||
|
*dram_logger_buf = scp_last_logger[pos];
|
||
|
pos++;
|
||
|
w_pos++;
|
||
|
dram_logger_buf++;
|
||
|
if (w_pos >= DRAM_BUF_LEN) {
|
||
|
/* warp */
|
||
|
pr_notice("[SCP] %s: dram warp\n", __func__);
|
||
|
w_pos = 0;
|
||
|
|
||
|
dram_logger_buf = ((char *) SCP_A_log_ctl) +
|
||
|
SCP_A_log_ctl->buff_ofs;
|
||
|
}
|
||
|
}
|
||
|
/* update write pointer */
|
||
|
SCP_A_buf_info->w_pos = w_pos;
|
||
|
}
|
||
|
exit:
|
||
|
/* SCP release awake */
|
||
|
if (scp_awake_flag == 0) {
|
||
|
if (scp_awake_unlock((void *)scp_id) == -1)
|
||
|
pr_debug("[SCP] %s: awake unlock fail\n", __func__);
|
||
|
}
|
||
|
|
||
|
mutex_unlock(&scp_logger_mutex);
|
||
|
if (pre_scp_logger_buf != NULL)
|
||
|
vfree(pre_scp_logger_buf);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* get log from scp and optionally save it
|
||
|
* NOTE: this function may be blocked
|
||
|
* @param scp_core_id: fill scp id to get last log
|
||
|
*/
|
||
|
void scp_get_log(enum scp_core_id scp_id)
|
||
|
{
|
||
|
pr_debug("[SCP] %s\n", __func__);
|
||
|
#if SCP_LOGGER_ENABLE
|
||
|
scp_A_get_last_log(last_log_info.scp_log_buf_maxlen);
|
||
|
/*move last log to dram*/
|
||
|
scp_crash_log_move_to_buf(scp_id);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* return useful log for aee issue dispatch
|
||
|
*/
|
||
|
#define CMP_SAFT_RANGE 176
|
||
|
#define DEFAULT_IDX (last_log_info.scp_log_buf_maxlen/3)
|
||
|
char *scp_pickup_log_for_aee(void)
|
||
|
{
|
||
|
char *last_log;
|
||
|
int i;
|
||
|
char keyword1[] = "coredump";
|
||
|
char keyword2[] = "exception";
|
||
|
|
||
|
if (scp_A_last_log == NULL)
|
||
|
return NULL;
|
||
|
last_log = &scp_A_last_log[DEFAULT_IDX]; /* default value */
|
||
|
|
||
|
for (i = last_log_info.scp_log_buf_maxlen; i >= CMP_SAFT_RANGE; i--) {
|
||
|
if (scp_A_last_log[i-0] != keyword1[7])
|
||
|
continue;
|
||
|
if (scp_A_last_log[i-1] != keyword1[6])
|
||
|
continue;
|
||
|
if (scp_A_last_log[i-2] != keyword1[5])
|
||
|
continue;
|
||
|
if (scp_A_last_log[i-3] != keyword1[4])
|
||
|
continue;
|
||
|
if (scp_A_last_log[i-4] != keyword1[3])
|
||
|
continue;
|
||
|
if (scp_A_last_log[i-5] != keyword1[2])
|
||
|
continue;
|
||
|
if (scp_A_last_log[i-6] != keyword1[1])
|
||
|
continue;
|
||
|
if (scp_A_last_log[i-7] != keyword1[0])
|
||
|
continue;
|
||
|
last_log = &scp_A_last_log[i-CMP_SAFT_RANGE];
|
||
|
return last_log;
|
||
|
}
|
||
|
|
||
|
for (i = last_log_info.scp_log_buf_maxlen; i >= CMP_SAFT_RANGE; i--) {
|
||
|
if (scp_A_last_log[i-0] != keyword2[8])
|
||
|
continue;
|
||
|
if (scp_A_last_log[i-1] != keyword2[7])
|
||
|
continue;
|
||
|
if (scp_A_last_log[i-2] != keyword2[6])
|
||
|
continue;
|
||
|
if (scp_A_last_log[i-3] != keyword2[5])
|
||
|
continue;
|
||
|
if (scp_A_last_log[i-4] != keyword2[4])
|
||
|
continue;
|
||
|
if (scp_A_last_log[i-5] != keyword2[3])
|
||
|
continue;
|
||
|
if (scp_A_last_log[i-6] != keyword2[2])
|
||
|
continue;
|
||
|
if (scp_A_last_log[i-7] != keyword2[1])
|
||
|
continue;
|
||
|
if (scp_A_last_log[i-8] != keyword2[0])
|
||
|
continue;
|
||
|
last_log = &scp_A_last_log[i-CMP_SAFT_RANGE];
|
||
|
return last_log;
|
||
|
}
|
||
|
return last_log;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* set scp_A_logger_inited
|
||
|
*/
|
||
|
void scp_logger_init_set(unsigned int value)
|
||
|
{
|
||
|
/*scp_A_logger_inited
|
||
|
* 0: logger not init
|
||
|
* 1: logger inited
|
||
|
*/
|
||
|
scp_A_logger_inited = value;
|
||
|
}
|
||
|
|