unplugged-kernel/drivers/misc/mediatek/eccci/fsm/mdee_dumper_v1.c

777 lines
25 KiB
C
Raw Normal View History

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2015 MediaTek Inc.
*/
#include <linux/kernel.h>
#include <linux/rtc.h>
#include <linux/timer.h>
#include "ccci_config.h"
#include "ccci_common_config.h"
#if defined(CONFIG_MTK_AEE_FEATURE)
#include <mt-plat/aee.h>
#endif
#include "mdee_dumper_v1.h"
#ifndef DB_OPT_DEFAULT
#define DB_OPT_DEFAULT (0) /* Dummy macro define to avoid build error */
#endif
#ifndef DB_OPT_FTRACE
#define DB_OPT_FTRACE (0) /* Dummy macro define to avoid build error */
#endif
static void ccci_aed_v1(struct ccci_fsm_ee *mdee, unsigned int dump_flag,
char *aed_str, int db_opt)
{
void *ex_log_addr = NULL;
int ex_log_len = 0;
void *md_img_addr = NULL;
int md_img_len = 0;
int info_str_len = 0;
char *buff; /*[AED_STR_LEN]; */
#if defined(CONFIG_MTK_AEE_FEATURE)
char buf_fail[] = "Fail alloc mem for exception\n";
#endif
char *img_inf;
int md_id = mdee->md_id;
struct mdee_dumper_v1 *dumper = mdee->dumper_obj;
struct ccci_smem_region *mdss_dbg =
ccci_md_get_smem_by_user_id(mdee->md_id,
SMEM_USER_RAW_MDSS_DBG);
struct ccci_mem_layout *mem_layout = ccci_md_get_mem(mdee->md_id);
struct ccci_per_md *per_md_data = ccci_get_per_md_data(mdee->md_id);
int md_dbg_dump_flag = per_md_data->md_dbg_dump_flag;
int ret = 0;
if (!mem_layout) {
CCCI_ERROR_LOG(md_id, FSM,
"%s:ccci_md_get_mem fail\n", __func__);
return;
}
buff = kmalloc(AED_STR_LEN, GFP_ATOMIC);
if (buff == NULL) {
CCCI_ERROR_LOG(md_id, FSM, "Fail alloc Mem for buff, %d!\n",
md_dbg_dump_flag);
goto err_exit1;
}
img_inf = ccci_get_md_info_str(md_id);
if (img_inf == NULL)
img_inf = "";
info_str_len = strlen(aed_str);
info_str_len += strlen(img_inf);
if (info_str_len > AED_STR_LEN)
/* Cut string length to AED_STR_LEN */
buff[AED_STR_LEN - 1] = '\0';
ret = snprintf(buff, AED_STR_LEN, "md%d:%s%s", md_id + 1, aed_str, img_inf);
if (ret < 0 || ret >= AED_STR_LEN)
CCCI_ERROR_LOG(md_id, FSM,
"%s-%d:snprintf fail,ret=%d\n",
__func__, __LINE__, ret);
/* MD ID must sync with aee_dump_ccci_debug_info() */
err_exit1:
if (dump_flag & CCCI_AED_DUMP_CCIF_REG) {
/* check this first, as we overwrite share memory here */
ex_log_addr = mdss_dbg->base_ap_view_vir;
ex_log_len = mdss_dbg->size;
ccci_md_dump_info(mdee->md_id,
DUMP_FLAG_CCIF | DUMP_FLAG_CCIF_REG,
mdss_dbg->base_ap_view_vir + CCCI_EE_OFFSET_CCIF_SRAM,
CCCI_EE_SIZE_CCIF_SRAM);
}
if (dump_flag & CCCI_AED_DUMP_EX_MEM) {
ex_log_addr = mdss_dbg->base_ap_view_vir;
ex_log_len = mdss_dbg->size;
}
if (dump_flag & CCCI_AED_DUMP_EX_PKT) {
ex_log_addr = (void *)&dumper->ex_info;
ex_log_len = sizeof(struct ex_log_t);
}
if (dump_flag & CCCI_AED_DUMP_MD_IMG_MEM) {
md_img_addr = (void *)mem_layout->md_bank0.base_ap_view_vir;
md_img_len = MD_IMG_DUMP_SIZE;
}
if (buff == NULL) {
#if defined(CONFIG_MTK_AEE_FEATURE)
if (md_dbg_dump_flag & (1 << MD_DBG_DUMP_SMEM))
aed_md_exception_api(ex_log_addr, ex_log_len,
md_img_addr, md_img_len, buf_fail, db_opt);
else
aed_md_exception_api(NULL, 0, md_img_addr, md_img_len,
buf_fail, db_opt);
#endif
} else {
#if defined(CONFIG_MTK_AEE_FEATURE)
if (md_dbg_dump_flag & (1 << MD_DBG_DUMP_SMEM))
aed_md_exception_api(ex_log_addr, ex_log_len,
md_img_addr, md_img_len, buff, db_opt);
else
aed_md_exception_api(NULL, 0, md_img_addr, md_img_len,
buff, db_opt);
#endif
kfree(buff);
}
}
static void mdee_dumper_info_dump_v1(struct ccci_fsm_ee *mdee)
{
struct mdee_dumper_v1 *dumper = mdee->dumper_obj;
int md_id = mdee->md_id;
char *ex_info;/* [EE_BUF_LEN] = ""; */
char *ex_info_temp = NULL;
/* [EE_BUF_LEN] = "\n[Others] May I-Bit dis too long\n"; */
char *i_bit_ex_info = NULL;
char buf_fail[] = "Fail alloc mem for exception\n";
int db_opt = (DB_OPT_DEFAULT | DB_OPT_FTRACE);
int dump_flag = 0;
struct debug_info_t *debug_info = &dumper->debug_info;
unsigned char c;
int md_state = ccci_fsm_get_md_state(mdee->md_id);
struct ccci_smem_region *mdccci_dbg =
ccci_md_get_smem_by_user_id(mdee->md_id,
SMEM_USER_RAW_MDCCCI_DBG);
struct ccci_smem_region *mdss_dbg =
ccci_md_get_smem_by_user_id(mdee->md_id,
SMEM_USER_RAW_MDSS_DBG);
struct rtc_time tm;
struct timeval tv = { 0 };
struct timeval tv_android = { 0 };
struct rtc_time tm_android;
struct ccci_per_md *per_md_data =
ccci_get_per_md_data(mdee->md_id);
int md_dbg_dump_flag = per_md_data->md_dbg_dump_flag;
int ret = 0;
do_gettimeofday(&tv);
tv_android = tv;
rtc_time_to_tm(tv.tv_sec, &tm);
tv_android.tv_sec -= sys_tz.tz_minuteswest * 60;
rtc_time_to_tm(tv_android.tv_sec, &tm_android);
CCCI_ERROR_LOG(md_id, FSM,
"Sync:%d%02d%02d %02d:%02d:%02d.%u(%02d:%02d:%02d.%03d(TZone))\n",
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec,
(unsigned int)tv.tv_usec,
tm_android.tm_hour, tm_android.tm_min, tm_android.tm_sec,
(unsigned int)tv_android.tv_usec);
ex_info = kmalloc(EE_BUF_LEN, GFP_ATOMIC);
if (ex_info == NULL) {
CCCI_ERROR_LOG(md_id, FSM, "Fail alloc Mem for ex_info!\n");
goto err_exit;
}
CCCI_ERROR_LOG(md_id, FSM, "exception type(%d):%s\n",
debug_info->type, debug_info->name ? : "Unknown");
switch (debug_info->type) {
case MD_EX_TYPE_ASSERT_DUMP:
/* Fall through */
case MD_EX_TYPE_ASSERT:
CCCI_NORMAL_LOG(md_id, FSM, "filename = %s\n",
debug_info->assert.file_name);
CCCI_NORMAL_LOG(md_id, FSM, "line = %d\n",
debug_info->assert.line_num);
CCCI_NORMAL_LOG(md_id, FSM,
"para0 = %d, para1 = %d, para2 = %d\n",
debug_info->assert.parameters[0],
debug_info->assert.parameters[1],
debug_info->assert.parameters[2]);
ret = snprintf(ex_info, EE_BUF_LEN,
"\n[%s] file:%s line:%d\np1:0x%08x\np2:0x%08x\np3:0x%08x\n",
debug_info->name,
debug_info->assert.file_name,
debug_info->assert.line_num,
debug_info->assert.parameters[0],
debug_info->assert.parameters[1],
debug_info->assert.parameters[2]);
break;
case MD_EX_TYPE_UNDEF:
/* Fall through */
case MD_EX_TYPE_SWI:
/* Fall through */
case MD_EX_TYPE_PREF_ABT:
/* Fall through */
case MD_EX_TYPE_DATA_ABT:
/* Fall through */
case MD_EX_TYPE_FATALERR_BUF:
/* Fall through */
case MD_EX_TYPE_FATALERR_TASK:
/* Fall through */
case MD_EX_TYPE_C2K_ERROR:
CCCI_NORMAL_LOG(md_id, FSM, "fatal error code 1 = %d\n",
debug_info->fatal_error.err_code1);
CCCI_NORMAL_LOG(md_id, FSM, "fatal error code 2 = %d\n",
debug_info->fatal_error.err_code2);
CCCI_NORMAL_LOG(md_id, FSM, "fatal error offender %s\n",
debug_info->fatal_error.offender);
if (debug_info->fatal_error.offender[0] != '\0') {
ret = snprintf(ex_info, EE_BUF_LEN,
"\n[%s] err_code1:%d err_code2:%d\nMD Offender:%s\n",
debug_info->name, debug_info->fatal_error.err_code1,
debug_info->fatal_error.err_code2,
debug_info->fatal_error.offender);
} else {
ret = snprintf(ex_info, EE_BUF_LEN,
"\n[%s] err_code1:%d err_code2:%d\n", debug_info->name,
debug_info->fatal_error.err_code1,
debug_info->fatal_error.err_code2);
}
break;
case CC_MD1_EXCEPTION:
CCCI_NORMAL_LOG(md_id, FSM, "fatal error code 1 = %d\n",
debug_info->fatal_error.err_code1);
CCCI_NORMAL_LOG(md_id, FSM, "fatal error code 2 = %d\n",
debug_info->fatal_error.err_code2);
ret = snprintf(ex_info, EE_BUF_LEN,
"\n[%s] err_code1:%d err_code2:%d\n",
debug_info->name,
debug_info->fatal_error.err_code1,
debug_info->fatal_error.err_code2);
break;
case MD_EX_TYPE_EMI_CHECK:
CCCI_NORMAL_LOG(md_id, FSM,
"md_emi_check: %08X, %08X, %02d, %08X\n",
debug_info->data.data0, debug_info->data.data1,
debug_info->data.channel, debug_info->data.reserved);
ret = snprintf(ex_info, EE_BUF_LEN,
"\n[emi_chk] %08X, %08X, %02d, %08X\n",
debug_info->data.data0, debug_info->data.data1,
debug_info->data.channel, debug_info->data.reserved);
break;
case DSP_EX_TYPE_ASSERT:
CCCI_NORMAL_LOG(md_id, FSM, "filename = %s\n",
debug_info->dsp_assert.file_name);
CCCI_NORMAL_LOG(md_id, FSM, "line = %d\n",
debug_info->dsp_assert.line_num);
CCCI_NORMAL_LOG(md_id, FSM, "exec unit = %s\n",
debug_info->dsp_assert.execution_unit);
CCCI_NORMAL_LOG(md_id, FSM,
"para0 = %d, para1 = %d, para2 = %d\n",
debug_info->dsp_assert.parameters[0],
debug_info->dsp_assert.parameters[1],
debug_info->dsp_assert.parameters[2]);
ret = snprintf(ex_info, EE_BUF_LEN,
"\n[%s] file:%s line:%d\nexec:%s\np1:%d\np2:%d\np3:%d\n",
debug_info->name, debug_info->assert.file_name,
debug_info->assert.line_num,
debug_info->dsp_assert.execution_unit,
debug_info->dsp_assert.parameters[0],
debug_info->dsp_assert.parameters[1],
debug_info->dsp_assert.parameters[2]);
break;
case DSP_EX_TYPE_EXCEPTION:
CCCI_NORMAL_LOG(md_id, FSM,
"exec unit = %s, code1:0x%08x\n",
debug_info->dsp_exception.execution_unit,
debug_info->dsp_exception.code1);
ret = snprintf(ex_info, EE_BUF_LEN,
"\n[%s] exec:%s code1:0x%08x\n", debug_info->name,
debug_info->dsp_exception.execution_unit,
debug_info->dsp_exception.code1);
break;
case DSP_EX_FATAL_ERROR:
CCCI_NORMAL_LOG(md_id, FSM, "exec unit = %s\n",
debug_info->dsp_fatal_err.execution_unit);
CCCI_NORMAL_LOG(md_id, FSM,
"err_code0 = 0x%08x, err_code1 = 0x%08x\n",
debug_info->dsp_fatal_err.err_code[0],
debug_info->dsp_fatal_err.err_code[1]);
ret = snprintf(ex_info, EE_BUF_LEN,
"\n[%s] exec:%s err_code1:0x%08x err_code2:0x%08x\n",
debug_info->name,
debug_info->dsp_fatal_err.execution_unit,
debug_info->dsp_fatal_err.err_code[0],
debug_info->dsp_fatal_err.err_code[1]);
break;
default: /* Only display exception name */
ret = snprintf(ex_info, EE_BUF_LEN, "\n[%s]\n", debug_info->name);
break;
}
if (ret < 0 || ret >= EE_BUF_LEN) {
CCCI_ERROR_LOG(md_id, FSM,
"%s-%d:snprintf fail,ret = %d,case_id = %d\n",
__func__, __LINE__, ret, debug_info->type);
goto err_exit;
}
/* Add additional info */
ex_info_temp = kmalloc(EE_BUF_LEN, GFP_ATOMIC);
if (ex_info_temp == NULL) {
CCCI_ERROR_LOG(md_id, FSM,
"Fail alloc Mem for ex_info_temp!\n");
goto err_exit;
}
ret = snprintf(ex_info_temp, EE_BUF_LEN, "%s", ex_info);
if (ret < 0 || ret >= EE_BUF_LEN) {
CCCI_ERROR_LOG(md_id, FSM,
"%s-%d:snprintf fail,ret = %d\n", __func__, __LINE__, ret);
goto err_exit;
}
switch (dumper->more_info) {
case MD_EE_CASE_ONLY_SWINT:
ret = snprintf(ex_info, EE_BUF_LEN, "%s%s", ex_info_temp,
"\nOnly SWINT case\n");
break;
case MD_EE_CASE_ONLY_EX:
ret = snprintf(ex_info, EE_BUF_LEN, "%s%s", ex_info_temp,
"\nOnly EX case\n");
break;
case MD_EE_CASE_NO_RESPONSE:
/* use strcpy, otherwise if this happens after a MD EE,
* the former EE info will be printed out
*/
strncpy(ex_info, "\n[Others] MD long time no response\n",
EE_BUF_LEN);
db_opt |= DB_OPT_FTRACE;
break;
case MD_EE_CASE_WDT:
strncpy(ex_info, "\n[Others] MD watchdog timeout interrupt\n",
EE_BUF_LEN);
break;
default:
break;
}
if (ret < 0 || ret >= EE_BUF_LEN) {
CCCI_ERROR_LOG(md_id, FSM,
"%s-%d:snprintf fail,ret = %d,case_id = %d\n",
__func__, __LINE__, ret, dumper->more_info);
goto err_exit;
}
/* get ELM_status field from MD side */
ret = snprintf(ex_info_temp, EE_BUF_LEN, "%s", ex_info);
if (ret < 0 || ret >= EE_BUF_LEN) {
CCCI_ERROR_LOG(md_id, FSM,
"%s-%d:snprintf fail,ret = %d\n", __func__, __LINE__, ret);
goto err_exit;
}
c = dumper->ex_info.envinfo.ELM_status;
CCCI_ERROR_LOG(md_id, FSM, "ELM_status: %x\n", c);
switch (c) {
case 0xFF:
ret = snprintf(ex_info, EE_BUF_LEN, "%s%s", ex_info_temp,
"\nno ELM info\n");
break;
case 0xAE:
ret = snprintf(ex_info, EE_BUF_LEN, "%s%s", ex_info_temp,
"\nELM rlat:FAIL\n");
break;
case 0xBE:
ret = snprintf(ex_info, EE_BUF_LEN, "%s%s", ex_info_temp,
"\nELM wlat:FAIL\n");
break;
case 0xDE:
ret = snprintf(ex_info, EE_BUF_LEN, "%s%s", ex_info_temp,
"\nELM r/wlat:PASS\n");
break;
default:
break;
}
if (ret < 0 || ret >= EE_BUF_LEN) {
CCCI_ERROR_LOG(md_id, FSM,
"%s-%d:snprintf fail,ret = %d,case_id = %d\n",
__func__, __LINE__, ret, c);
}
err_exit:
/* Dump MD EE info */
CCCI_MEM_LOG_TAG(md_id, FSM, "Dump MD EX log\n");
if ((md_id == MD_SYS3)
|| (dumper->more_info == MD_EE_CASE_NORMAL
&& md_state == BOOT_WAITING_FOR_HS1)) {
ccci_util_mem_dump(md_id, CCCI_DUMP_MEM_DUMP,
&dumper->ex_info, sizeof(struct ex_log_t));
} else if (md_dbg_dump_flag & (1 << MD_DBG_DUMP_SMEM)) {
ccci_util_mem_dump(md_id, CCCI_DUMP_MEM_DUMP,
mdccci_dbg->base_ap_view_vir, mdccci_dbg->size);
ccci_util_mem_dump(md_id, CCCI_DUMP_MEM_DUMP,
mdss_dbg->base_ap_view_vir, mdss_dbg->size);
}
if (dumper->more_info == MD_EE_CASE_NORMAL
&& md_state == BOOT_WAITING_FOR_HS1) {
/* MD will not fill in share memory
* before we send runtime data
*/
dump_flag = CCCI_AED_DUMP_EX_PKT;
} else {
/*
* otherwise always dump whole share memory,
* as MD will fill debug log into
* its 2nd 1K region after bootup
*/
dump_flag = CCCI_AED_DUMP_EX_MEM;
if (dumper->more_info == MD_EE_CASE_NO_RESPONSE)
dump_flag |= CCCI_AED_DUMP_CCIF_REG;
}
/* update here to maintain handshake stage
* info during exception handling
*/
if (debug_info->type == MD_EX_TYPE_C2K_ERROR
&& debug_info->fatal_error.err_code1 == MD_EX_C2K_FATAL_ERROR)
CCCI_ERROR_LOG(md_id, FSM, "C2K EE, No need trigger DB\n");
else if (debug_info->type == CC_MD1_EXCEPTION)
CCCI_ERROR_LOG(md_id, FSM, "MD1 EE, No need trigger DB\n");
else if (ex_info == NULL)
ccci_aed_v1(mdee, dump_flag, buf_fail, db_opt);
else
ccci_aed_v1(mdee, dump_flag, ex_info, db_opt);
kfree(ex_info);
kfree(ex_info_temp);
kfree(i_bit_ex_info);
}
/*
* copy raw data (struct ex_log_t) received from md into struct debug_info_t
*/
static void mdee_dumper_info_prepare_v1(struct ccci_fsm_ee *mdee)
{
struct ex_log_t *ex_info;
int ee_type, ee_case;
struct mdee_dumper_v1 *dumper = mdee->dumper_obj;
int md_id = mdee->md_id;
struct debug_info_t *debug_info = &dumper->debug_info;
struct ccci_mem_layout *mem_layout = ccci_md_get_mem(mdee->md_id);
struct ccci_smem_region *mdss_dbg =
ccci_md_get_smem_by_user_id(mdee->md_id,
SMEM_USER_RAW_MDSS_DBG);
int ret = 0;
int val = 0;
if (debug_info == NULL)
return;
if (mem_layout == NULL) {
CCCI_ERROR_LOG(md_id, FSM,
"ccci_md_get_mem fail\n");
return;
}
if ((md_id == MD_SYS3) ||
(dumper->more_info == MD_EE_CASE_NORMAL
&& ccci_fsm_get_md_state(mdee->md_id)
== BOOT_WAITING_FOR_HS1)) {
ex_info = &dumper->ex_info;
CCCI_DEBUG_LOG(md_id, FSM,
"Parse ex info from ccci packages\n");
} else {
ex_info = (struct ex_log_t *)mdss_dbg->base_ap_view_vir;
CCCI_DEBUG_LOG(md_id, FSM,
"Parse ex info from shared memory\n");
}
ee_case = dumper->more_info;
memset(debug_info, 0, sizeof(struct debug_info_t));
ee_type = ex_info->header.ex_type;
debug_info->type = ee_type;
mdee->ex_type = ee_type;
if (*((char *)ex_info + CCCI_EXREC_OFFSET_OFFENDER) != 0xCC) {
memcpy(debug_info->fatal_error.offender,
(char *)ex_info + CCCI_EXREC_OFFSET_OFFENDER,
sizeof(debug_info->fatal_error.offender) - 1);
debug_info->fatal_error.offender[
sizeof(debug_info->fatal_error.offender) - 1] = '\0';
} else {
debug_info->fatal_error.offender[0] = '\0';
}
switch (ee_type) {
case MD_EX_TYPE_INVALID:
debug_info->name = "INVALID";
break;
case MD_EX_TYPE_UNDEF:
debug_info->name = "Fatal error (undefine)";
debug_info->fatal_error.err_code1 =
ex_info->content.fatalerr.error_code.code1;
debug_info->fatal_error.err_code2 =
ex_info->content.fatalerr.error_code.code2;
break;
case MD_EX_TYPE_SWI:
debug_info->name = "Fatal error (swi)";
debug_info->fatal_error.err_code1 =
ex_info->content.fatalerr.error_code.code1;
debug_info->fatal_error.err_code2 =
ex_info->content.fatalerr.error_code.code2;
break;
case MD_EX_TYPE_PREF_ABT:
debug_info->name = "Fatal error (prefetch abort)";
debug_info->fatal_error.err_code1 =
ex_info->content.fatalerr.error_code.code1;
debug_info->fatal_error.err_code2 =
ex_info->content.fatalerr.error_code.code2;
break;
case MD_EX_TYPE_DATA_ABT:
debug_info->name = "Fatal error (data abort)";
debug_info->fatal_error.err_code1 =
ex_info->content.fatalerr.error_code.code1;
debug_info->fatal_error.err_code2 =
ex_info->content.fatalerr.error_code.code2;
break;
case MD_EX_TYPE_ASSERT:
debug_info->name = "ASSERT";
if (md_id == MD_SYS3) {
ret = snprintf(debug_info->assert.file_name,
sizeof(debug_info->assert.file_name),
ex_info->content.c2k_assert.filename);
debug_info->assert.line_num =
ex_info->content.c2k_assert.linenumber;
debug_info->assert.parameters[0] =
ex_info->content.c2k_assert.parameters[0];
debug_info->assert.parameters[1] =
ex_info->content.c2k_assert.parameters[1];
debug_info->assert.parameters[2] =
ex_info->content.c2k_assert.parameters[2];
} else {
ret = snprintf(debug_info->assert.file_name,
sizeof(debug_info->assert.file_name),
ex_info->content.assert.filename);
debug_info->assert.line_num =
ex_info->content.assert.linenumber;
debug_info->assert.parameters[0] =
ex_info->content.assert.parameters[0];
debug_info->assert.parameters[1] =
ex_info->content.assert.parameters[1];
debug_info->assert.parameters[2] =
ex_info->content.assert.parameters[2];
}
if (ret < 0 || ret >= sizeof(debug_info->assert.file_name))
CCCI_ERROR_LOG(md_id, FSM,
"%s-%d:snprintf fail,ret = %d\n", __func__, __LINE__, ret);
break;
case MD_EX_TYPE_FATALERR_TASK:
debug_info->name = "Fatal error (task)";
debug_info->fatal_error.err_code1 =
ex_info->content.fatalerr.error_code.code1;
debug_info->fatal_error.err_code2 =
ex_info->content.fatalerr.error_code.code2;
break;
case MD_EX_TYPE_C2K_ERROR:
debug_info->name = "Fatal error (C2K_EXP)";
debug_info->fatal_error.err_code1 =
ex_info->content.fatalerr.error_code.code1;
debug_info->fatal_error.err_code2 =
ex_info->content.fatalerr.error_code.code2;
break;
case CC_MD1_EXCEPTION:
debug_info->name = "Fatal error (LTE_EXP)";
debug_info->fatal_error.err_code1 =
ex_info->content.fatalerr.error_code.code1;
debug_info->fatal_error.err_code2 =
ex_info->content.fatalerr.error_code.code2;
break;
case MD_EX_TYPE_FATALERR_BUF:
debug_info->name = "Fatal error (buff)";
debug_info->fatal_error.err_code1 =
ex_info->content.fatalerr.error_code.code1;
debug_info->fatal_error.err_code2 =
ex_info->content.fatalerr.error_code.code2;
break;
case MD_EX_TYPE_LOCKUP:
debug_info->name = "Lockup";
break;
case MD_EX_TYPE_ASSERT_DUMP:
debug_info->name = "ASSERT DUMP";
if (md_id == MD_SYS3) {
ret = snprintf(debug_info->assert.file_name,
sizeof(debug_info->assert.file_name),
ex_info->content.c2k_assert.filename);
debug_info->assert.line_num =
ex_info->content.c2k_assert.linenumber;
} else {
ret = snprintf(debug_info->assert.file_name,
sizeof(debug_info->assert.file_name),
ex_info->content.assert.filename);
debug_info->assert.line_num =
ex_info->content.assert.linenumber;
}
if (ret < 0 || ret >= sizeof(debug_info->assert.file_name))
CCCI_ERROR_LOG(md_id, FSM,
"%s-%d:snprintf fail,ret = %d\n", __func__, __LINE__, ret);
break;
case DSP_EX_TYPE_ASSERT:
debug_info->name = "MD DMD ASSERT";
if (md_id == MD_SYS3) {
ret = snprintf(debug_info->dsp_assert.file_name,
sizeof(debug_info->dsp_assert.file_name),
ex_info->content.c2k_assert.filename);
debug_info->dsp_assert.line_num =
ex_info->content.c2k_assert.linenumber;
val = snprintf(debug_info->dsp_assert.execution_unit,
sizeof(debug_info->dsp_assert.execution_unit),
ex_info->envinfo.execution_unit);
debug_info->dsp_assert.parameters[0] =
ex_info->content.c2k_assert.parameters[0];
debug_info->dsp_assert.parameters[1] =
ex_info->content.c2k_assert.parameters[1];
debug_info->dsp_assert.parameters[2] =
ex_info->content.c2k_assert.parameters[2];
} else {
ret = snprintf(debug_info->dsp_assert.file_name,
sizeof(debug_info->dsp_assert.file_name),
ex_info->content.assert.filename);
debug_info->dsp_assert.line_num =
ex_info->content.assert.linenumber;
val = snprintf(debug_info->dsp_assert.execution_unit,
sizeof(debug_info->dsp_assert.execution_unit),
ex_info->envinfo.execution_unit);
debug_info->dsp_assert.parameters[0] =
ex_info->content.assert.parameters[0];
debug_info->dsp_assert.parameters[1] =
ex_info->content.assert.parameters[1];
debug_info->dsp_assert.parameters[2] =
ex_info->content.assert.parameters[2];
}
if (ret < 0 || ret >= sizeof(debug_info->dsp_assert.file_name)) {
CCCI_ERROR_LOG(md_id, FSM,
"%s-%d:snprintf fail,ret = %d\n", __func__, __LINE__, ret);
break;
}
if (val < 0 || val >= sizeof(debug_info->dsp_assert.execution_unit))
CCCI_ERROR_LOG(md_id, FSM,
"%s-%d:snprintf fail,val = %d\n", __func__, __LINE__, val);
break;
case DSP_EX_TYPE_EXCEPTION:
debug_info->name = "MD DMD Exception";
ret = snprintf(debug_info->dsp_exception.execution_unit,
sizeof(debug_info->dsp_exception.execution_unit),
ex_info->envinfo.execution_unit);
if (ret < 0 || ret >= sizeof(debug_info->dsp_exception.execution_unit))
CCCI_ERROR_LOG(md_id, FSM,
"%s-%d:snprintf fail,ret = %d\n", __func__, __LINE__, ret);
debug_info->dsp_exception.code1 =
ex_info->content.fatalerr.error_code.code1;
break;
case DSP_EX_FATAL_ERROR:
debug_info->name = "MD DMD FATAL ERROR";
ret = snprintf(debug_info->dsp_fatal_err.execution_unit,
sizeof(debug_info->dsp_fatal_err.execution_unit),
ex_info->envinfo.execution_unit);
if (ret < 0 || ret >= sizeof(debug_info->dsp_fatal_err.execution_unit))
CCCI_ERROR_LOG(md_id, FSM,
"%s-%d:snprintf fail,ret = %d\n", __func__, __LINE__, ret);
debug_info->dsp_fatal_err.err_code[0] =
ex_info->content.fatalerr.error_code.code1;
debug_info->dsp_fatal_err.err_code[1] =
ex_info->content.fatalerr.error_code.code2;
break;
default:
debug_info->name = "UNKNOWN Exception";
break;
}
debug_info->ext_mem = ex_info;
debug_info->ext_size = sizeof(struct ex_log_t);
debug_info->md_image = (void *)mem_layout->md_bank0.base_ap_view_vir;
debug_info->md_size = MD_IMG_DUMP_SIZE;
}
static void mdee_dumper_v1_set_ee_pkg(struct ccci_fsm_ee *mdee,
char *data, int len)
{
struct mdee_dumper_v1 *dumper = mdee->dumper_obj;
int cpy_len =
len > sizeof(struct ex_log_t) ? sizeof(struct ex_log_t) : len;
memcpy(&dumper->ex_info, data, cpy_len);
}
static void mdee_dumper_v1_dump_ee_info(struct ccci_fsm_ee *mdee,
enum MDEE_DUMP_LEVEL level, int more_info)
{
struct mdee_dumper_v1 *dumper = mdee->dumper_obj;
int md_id = mdee->md_id;
struct ccci_smem_region *mdccci_dbg =
ccci_md_get_smem_by_user_id(mdee->md_id,
SMEM_USER_RAW_MDCCCI_DBG);
struct ccci_smem_region *mdss_dbg =
ccci_md_get_smem_by_user_id(mdee->md_id,
SMEM_USER_RAW_MDSS_DBG);
char ex_info[EE_BUF_LEN] = {0};
int md_state = ccci_fsm_get_md_state(mdee->md_id);
struct ccci_per_md *per_md_data = ccci_get_per_md_data(mdee->md_id);
int md_dbg_dump_flag = per_md_data->md_dbg_dump_flag;
int ret = 0;
dumper->more_info = more_info;
if (level == MDEE_DUMP_LEVEL_BOOT_FAIL) {
if (md_state == BOOT_WAITING_FOR_HS1) {
ret = snprintf(ex_info, EE_BUF_LEN,
"\n[Others] MD_BOOT_UP_FAIL(HS%d)\n", 1);
/* Handshake 1 fail */
ccci_aed_v1(mdee,
CCCI_AED_DUMP_CCIF_REG | CCCI_AED_DUMP_MD_IMG_MEM,
ex_info, DB_OPT_DEFAULT);
} else if (md_state == BOOT_WAITING_FOR_HS2) {
ret = snprintf(ex_info, EE_BUF_LEN,
"\n[Others] MD_BOOT_UP_FAIL(HS%d)\n", 2);
/* Handshake 2 fail */
CCCI_MEM_LOG_TAG(md_id, FSM, "Dump MD EX log\n");
if (md_dbg_dump_flag & (1 << MD_DBG_DUMP_SMEM)) {
ccci_util_mem_dump(md_id, CCCI_DUMP_MEM_DUMP,
mdccci_dbg->base_ap_view_vir,
mdccci_dbg->size);
ccci_util_mem_dump(md_id, CCCI_DUMP_MEM_DUMP,
mdss_dbg->base_ap_view_vir,
mdss_dbg->size);
}
ccci_aed_v1(mdee,
CCCI_AED_DUMP_CCIF_REG | CCCI_AED_DUMP_EX_MEM,
ex_info, DB_OPT_FTRACE);
}
if (ret < 0 || ret >= EE_BUF_LEN) {
CCCI_ERROR_LOG(md_id, FSM,
"%s-%d:snprintf fail,ret = %d\n", __func__, __LINE__, ret);
return;
}
} else if (level == MDEE_DUMP_LEVEL_STAGE1) {
if (md_dbg_dump_flag & (1 << MD_DBG_DUMP_SMEM)) {
CCCI_MEM_LOG_TAG(md_id, FSM, "Dump MD exp smem_log\n");
ccci_util_mem_dump(md_id, CCCI_DUMP_MEM_DUMP,
mdccci_dbg->base_ap_view_vir, mdccci_dbg->size);
ccci_util_mem_dump(md_id, CCCI_DUMP_MEM_DUMP,
mdss_dbg->base_ap_view_vir, mdss_dbg->size);
}
} else if (level == MDEE_DUMP_LEVEL_STAGE2) {
mdee_dumper_info_prepare_v1(mdee);
mdee_dumper_info_dump_v1(mdee);
} else {
}
}
static struct md_ee_ops mdee_ops_v1 = {
.dump_ee_info = &mdee_dumper_v1_dump_ee_info,
.set_ee_pkg = &mdee_dumper_v1_set_ee_pkg,
};
int mdee_dumper_v1_alloc(struct ccci_fsm_ee *mdee)
{
struct mdee_dumper_v1 *dumper;
int md_id = mdee->md_id;
/* Allocate port_proxy obj and set all member zero */
dumper = kzalloc(sizeof(struct mdee_dumper_v1), GFP_KERNEL);
if (dumper == NULL) {
CCCI_ERROR_LOG(md_id, FSM,
"%s:alloc mdee_parser_v1 fail\n", __func__);
return -1;
}
mdee->dumper_obj = dumper;
mdee->ops = &mdee_ops_v1;
return 0;
}